LLM API上线仅三个月,工单系统就快被用户提问冲垮了。不是人力不够,是每张工单没法快速判断该转给谁、该用什么流程处理:是模型输出报错,还是配额用完了,还是内容安全误杀,还是用户觉得效果不好单纯来投诉?每张单都要人工点开、阅读、判断、选标签,一天的吞吐量直接卡死。这不是某一家的特例,凡是接了LLM API的业务团队,走到一定规模都会撞上同一个词:工单打标。
工单打标,简单说就是给用户提交的反馈盖一个分类章,标注它属于什么问题域、什么紧急程度、该走哪条处理管线。但当工单内容来自LLM API时,事情变得微妙起来——因为工单文本本身可能就是模型的输入输出、报错JSON、Token消耗记录。给这类工单打标,既不同于传统客服工单分类,也不同于普通文本分类任务。
我前后在两个团队里实践过LLM API工单打标这件事,也调研过不少同行的方案。目前行业内真正被反复提及的主流做法大概有五种,背后还有几个绕不开的争议点。这篇文章把我的实操观察和踩坑记录整理成文,给正在做类似系统的同学一个参照系。
1. 先搞清楚:LLM API工单打标为什么特殊
1.1 工单内容的复杂度远高于普通客服文本
传统客服工单大多是自然语言描述:“我登录不了”“订单没到账”这类。但LLM API工单里经常混着好几类信息:用户粘贴的原始请求、模型返回的响应片段、带Error Code的调用日志、Token消耗统计、甚至用户对输出质量的吐槽。同一个工单里可能同时包含“调用报错”和“回答质量不满意”两个线索。
这意味着打标不能只看表面文字,得从结构里去拆。比如一个工单写着“改一下温度参数后直接400了”,如果只是做关键词匹配,可能落入“参数设置”类别,但实际问题是API网关限流或模型服务不可用。文本之外还有元数据可利用,这对打标方案的设计有直接影响。
1.2 打标结果的消费方不止一个
工单打标的标签,不只是给客服看的。在LLM API场景下,同一套标签体系至少服务四类下游:
- 运维团队:区分“模型崩溃”“网络超时”“限流”等基础设施问题,负责SLO与告警
- 产品团队:判断用户高频痛点集中在“效果质量”还是“易用性”,决定功能优化优先级
- 算法团队:识别典型bad case,筛选Prompt质量,为微调和RAG优化提供语料线索
- 财务/运营团队:统计成本相关工单,比如Token浪费、计费争议
如果标签体系没对齐多方需求,打标结果就会沦为“客服自己看着舒服,别人全不认可”的自嗨产物。别急着定方案,先把标签消费方和标签粒度聊清楚。
1.3 工单量级和时延要求决定技术路线
不同阶段对打标方案的约束完全不一样。日工单量只有几十张时,人工分类完全够;涨到几千张时,人肉打标开始漏单,需要自动化;涨到日万级并且还要实时路由时,打标延迟就变成硬指标了——有的团队要求从工单进入系统到自动分派出去不超过3秒,这时某些方案直接被淘汰。
我见过最典型的认知误区是把工单打标当成纯离线任务,只追求最终准确率。实际上一旦接入自动化工单路由,打标的“响应速度”和“可解释性”就比准确率更优先。下面讲五种方案,我都会从准确率、延迟、成本、可维护性四个维度来对比。
2. 五条技术路线逐一拆解:从规则到LLM到闭环系统
2.1 方式一:基于关键词与正则表达式的规则打标
这是最古老也最基础的方式。预先维护一个关键词库和正则规则库,当工单标题、描述或元数据命中某个模式时,直接赋予标签。比如工单里出现“context window exceeded”“400 context_length_exceeded”就归为“上下文超限”,出现“rate limit”“429”归为“限流”。
规则打标的优势在于极低延迟、完全可解释、单次成本趋近于零,并且线上排障时可以直接告诉用户“系统根据你工单里的哪个词判定了什么类型”。对于强特征问题——限流、鉴权失败、模型不存在、余额不足——规则方式至今仍是最可靠的。
但规则方式有两个致命问题:一是规则维护成本会随着工单形态增加而暴涨。LLM API的错误信息五花八门,同一个底层错误可能以各种措辞出现,为每个措辞都补一条正则,规则库最终会变成谁都不敢动的怪物。二是语义型标签规则打不了。用户写“模型总是一本正经胡说八道”,这种描述“幻觉类问题”的工单没有任何强特征词,规则只能干瞪眼。
我的建议是:规则方式永远保留,用作第一层漏斗,专门过滤高频、强特征、稳定不变的类别,但别指望它解决所有问题。规则覆盖率能做到40%-50%已经非常健康,剩下交给其他手段。
2.2 方式二:基于传统机器学习分类器的监督打标
思路并不复杂:把工单文本转成特征(TF-IDF、词频、N-gram等),喂给逻辑回归、朴素贝叶斯、支持向量机或随机森林,训练一个分类器来预测标签。这需要先积累一批人工标注过的工单数据,用来做训练集。
传统机器学习方案放在今天看,最大的价值在于运行成本低、推理快,而且分类结果可以通过特征权重解释——逻辑回归能看到哪些词把工单推向某个标签。在LLM API场景中,它比纯规则能覆盖更多语义化的表达,比如用户说“模型把我代码改坏了”和“代码被篡改了”都能聚到“输出质量异常”。
但传统机器学习方案有两个比较难受的地方:
- 特征工程和训练的迭代周期长。标签体系一旦调整,又要重新做标注、重训模型。
- 对长尾新兴问题不敏感。今天是“上下文超限”,明天可能是“JSON模式解析失败”,模型没见过这类样本就很难正确分类,而标注新样本再重训的成本并不低。
实际操作中还容易踩标注口径不一致的坑。两个人标同一张工单,一个人按“API调用错误”标,另一个人按“代码逻辑问题”标。这类标注噪声直接决定了上界,模型再好也突破不了数据质量的上限。传统ML作为中等规模场景的过渡方案是合理的,但如果团队人力有限,我不建议在它身上投入过多,很多团队做完一轮就转投LLM了。
2.3 方式三:基于Embedding的向量相似度打标
这种方式的思路是:不再硬匹配关键词,而是把工单文本通过嵌入模型转成向量,然后与已标记过、已分好类别的“模板向量库”计算相似度。工单进来后,找到最近邻的已打标模板,沿用其标签。
这类方案适合“语义相似但用词完全不同”的工单召回。相比传统ML,它不需要显式的特征工程和模型训练,只需配置模板和阈值。现在用开源的文本嵌入模型或商用Embedding API都能直接获得不错的向量表示,而且阈值可调,便于控制误判率。
但这种方式有几个经验教训:
- 模板质量直接决定打标上限。模板太少、类别覆盖不全,一个相似的就误入歧途。我见过团队拿300个模板就想打全所有工单,结果召回率惨不忍睹。
- 阈值设置极其折磨。阈值太高,大量工单落不到任何标签,退回人工;阈值太低,无关工单乱贴标签。单一全局阈值并不稳定,不同类别可能需要各自的阈值。
- 语义相似不等于语义同质。用户说“模型输出全是英文”和“模型翻译成英文了”向量上可能很近,但一个是投诉,一个是功能使用问题,标签不同。Embedding天然不擅长捕捉这种细微但关键的品类边界。
老实说,向量相似度打标在推荐、搜索场景很能打,但在工单打标这种“类别边界敏感、需要精确语义判定”的场景里只能当辅助,不能当主力。如果要做,建议把阈值调得保守一点,宁可漏标退回人工,也不要乱标。
2.4 方式四:基于LLM的零样本/少样本提示分类
直接把工单文本发给LLM,在Prompt里定义标签体系、打标规则、输出格式,让模型返回一个JSON结果。这就是目前话题度最高、争议也最多的LLM分类路线。
LLM分类的核心优势有三点:
- 零样本泛化。不需要提前标注大量数据,新标签体系通过Prompt就能切换。
- 语义理解能力强。能够理解反讽、模糊表达和复合型问题,从整段工单中提炼真正的主诉。
- 可附带推理依据。让模型输出label的同时给出reason,打标结果不再是黑盒。
实践方式通常分为两种:一种是直接调用通用LLM API,把工单内容放进Prompt;另一种是自建微调的专用分类模型。后者如果是针对分类任务做微调,可以比通用模型更快、更便宜,但前提是有足够的高质量标注数据——绕了一圈又回到了数据问题。
关于Prompt如何设计,我分享一个稳定可用的模板骨架。这个模板我前后改了很多版,关键点在于:明确任务、限定输出、要求每张单给出置信度和依据,然后把所有可能出现的特殊边界写清楚。
你是一个工单分类助手。下面是一张LLM API技术支持工单。 请根据以下标签体系,为工单选择一个主标签(primary_label)。 标签体系: - api_error: API调用报错,包括HTTP错误、参数错误、鉴权失败 - quota_and_billing: 配额不足、账单、限额相关 - model_quality: 模型输出内容质量不佳,包括幻觉、跑题、拒答、格式错误 - safety_and_moderation: 内容安全拦截、敏感词误杀 - latency_and_timeout: 请求超时、响应过慢、连接中断 - usage_guidance: 用户不熟悉API用法,需要使用指导 - others: 无法归入以上类的工单 规则: 1. 如果工单同时涉及多个问题,选择影响用户核心诉求的标签。 2. 如果工单包含明确错误码且与调用链路相关,优先归为api_error。 3. 只输出JSON,格式为:{"primary_label": "...", "confidence": 0到1之间的数字, "reason": "不超过30字的中文依据"}。 4. 不要输出任何其他文字。 工单内容: {工单全文}实践经验告诉我,Prompt里最不能省的是“特殊优先级规则”和“严格输出格式”。没有规则的LLM分类容易发散,一会儿按意图分,一会儿按错误类型分;不限定JSON格式,后处理解析文本时会疯掉。另外,为了省Token,工单过长时我会做截断——保留开头70%和结尾报错/异常部分,因为这俩位置通常信息密度最高。中间偶尔有线索,但为了控制成本可以舍弃。
关于模型参数,做分类问题时有一组相对靠谱的设置:
- temperature设到0或最低档。分类任务不需要创造性,需要稳定性。
- max_tokens只需要能容纳JSON和reason长度,一般256到512足够,开太大不仅慢还贵。
- 如果有条件,在API调用里把response_format设为json_object之类,避免解析错乱。
LLM分类的劣势也直接摆在台面上:单次调用有Token成本;在高并发工单场景下,延迟和并发上限制约吞吐;更重要的是,当工单内容被发送到第三方LLM API时,涉及数据边界问题。这些争议留到第3章详细展开。
2.5 方式五:主动学习与人机协同的闭环打标
如果你面对的工单量达到数千日单,且标签体系还在不断演化,前四种方式单独拎出来都不够用,实际生产中更容易见到的是把多种策略组合成“打标漏斗”,再配合人工抽检形成闭环。
一个理想的闭环打标系统大致是:
- 规则层率先过滤强特征工单,贡献确定性的标签。
- Embedding相似度层捕获语义相邻但非强关键词的长尾描述。
- LLM层兜底处理前两层都无法稳定判定的复杂工单。
- 落入“低置信度”状态的工单进入人工队列。
- 人工打标结果定期回流,一部分扩充模板库,一部分成为模型微调数据,另一部分反向修订规则。
这才是真正能够长期生长的打标方案。前三层接力完成自动化,第四层解决机器没法判断的边界案例,第五层保证系统随着工单形态演化而持续迭代。主动学习在这里的价值是:不是随机抽检,而是优先抽出模型置信度低、边界模糊、分歧大的工单给人看,让每一份人工投入都产生最大的系统增益。
我团队一开始只有“规则+人工”,后来加了LLM作为中间层,再后来加了主动学习采样做抽检,准确率和召回率的提升曲线完全不一样。纯规则阶段准确率高但召回低;引入LLM后召回涨了,但偶尔跑出离谱标签;加上主动学习闭环后,整体指标才稳定下来。
3. 核心争议:成本、可信度、隐私和标签体系
3.1 争议一:LLM给的标签,到底能不能信?
先说结论:能信一部分,但要把它当成“一个聪明但偶尔粗心的实习生”,不能当成可靠的自动化螺丝钉。LLM分类最危险的场景不是它错,而是它错得振振有词。Prompt里让它给reason,它可能编一个看起来非常专业的理由,实际上依据错误。
我在实践中遇到过一件很典型的事:工单是用户发来的“你的模型API接口崩溃了”,LLM把primary_label判定为“api_error”,reason写的“用户报告接口崩溃显示出服务端故障信号”,看起来没问题。但仔细看工单正文才知道,用户所谓“崩溃”是指自己代码里没有做异常捕获导致程序退出,整个错误完全发生在用户侧代码里。这种“表面抱怨、实际误用”的工单,正是LLM分类翻车的高发区。反过来,规则和传统ML模型面对这种文本,反而因为找不到强特征而倾向放弃,不会硬给结论。
处理办法是给LLM分类增加一个“拒答”出口。Prompt明确要求:当模型无法判断或信息不足时,输出low_confidence并交给人工。坏标签比没有标签更棘手,因为坏标签会带着工单走进错误的下游流程,校正成本更高。
3.2 争议二:Token成本和延迟这笔账怎么算?
LLM API打标不是免费的。假设一张工单平均800字,填进Prompt加上标签体系,再算输出部分,一次分类可能消耗1200到1800个Token。按常见通用模型API价格计算,一张工单的分类成本大概是几厘钱到几分钱之间。看起来不多,但日工单上万张时,这笔支出每个月可能就是几千到几万元,而且这部分钱完全不会带来直接商业回报。
延迟也一样。单次LLM调用通常需要几百毫秒到几秒,并发的工单涌入时,如果放任所有工单都走LLM打标,等待队列会拖垮路由SLA。为了不让打标成为工单处理的瓶颈,我一般建议设定“延迟预算”:快速层必须在50毫秒内给出结果,慢速层最多再花2秒,超时一律交给异步队列处理,不能阻塞主链路。
成本优化的实践思路也很清晰:能交给规则的就不要交给向量库,能交给向量库的不要交给LLM,把LLM花在最需要语义理解的边缘Case上。按这个漏斗结构,最终只有20%-30%的工单实际走到LLM层,成本就能压到可接受范围。
3.3 争议三:数据隐私与数据边界问题
这是最容易被忽略但最后往往变成一票否决的争议。工单内容天然包含用户代码片段、业务数据、API密钥痕迹、模型输入输出对。这些数据发往第三方LLM API做分类时,等于把客户的数据送出了自己的隔离环境。
如果Tech团队只在内部私有化部署的开源模型上做分类,就没有这个问题,安全性和成本都可控。但前提是团队有推理资源,并且模型效果必须足够好到能承担分类任务。如果只能用外部商业API,至少要过两关:
- 脱敏关:在发送前对工单文本做脱敏,把疑似KEY、Token、手机号、邮箱等敏感字段替换成占位符,再从工单里抽取必要的特征文本,而不是把整个工单原文丢出去。
- 审批关:数据出口合规评审要做在前面,不能等上线了被合规团队找上门再回滚。
分类任务和内容生成任务对被处理数据的敏感度要求不一样。打标只是一个判断过程,产出的只有标签和依据,原理上不需要输出正文,所以数据最小化原则在此场景下是可行的。
3.4 争议四:标签体系本身就是最大的不确定性
很多时候打不准不是模型的问题,是标签体系定义得糊里糊涂。团队里每个人对“模型质量”的理解不一样:有人觉得“输出英文就是质量差”,有人觉得“只要截断、拒答、胡编才算质量差”。没有统一的标注口径,给任何模型训练或评估都埋了雷。
我给团队做标签定义时,每个标签都带着两条来说明:正例(归入这类的情况)和易混淆负例(看起来像但不归入这类的情况)。例如:
- 标签:model_quality
- 正例:模型输出明显跑题、逻辑错误、内容编造、回答被截断、格式不符
- 易混淆负例:API连接正常但用户单纯不满意回复长度,如果只是嫌短而回复本身没问题,更接近usage_guidance而非model_quality
这本质上是在给机器写“分类标准操作程序”。标签定义清晰程度直接决定打标的可复现性,也决定了不同自动策略能否达成一致。
另外标签体系要允许“增长”。用户永远会提出标签体系没预见到的新问题。固定的单标签强制分类会把所有未知工单都挤到“others”里,而一个膨胀的“others”等于没有打标。可行的处理是设计双层标签:第一层是粗粒度类别,稳定不变;第二层是细粒度描述,允许随真实案例增加而扩展。粗粒度用于路由、统计和训练,细粒度用于定位和复盘。
4. 实操:一个可复现的混合打标方案全过程
4.1 第一步:盘现状,定标签,建评测集
动工之前先盘清楚三件事:历史工单量级是多少、现有标签体系能用吗、有没有人工标注过的历史数据。没有历史标注不要紧,抽300到500张工单,覆盖常见错误码和用户表述,让两个人独立标注,再合并讨论出最终标签。这批数据有两个用途:既是初始化模板库的种子,也是后续评测分类效果的基准集。
评测集的重要性被我反复验证过——没有基准,你都不知道在一次Prompt调整或模型替换中,打标到底变好了还是变坏了。基准集至少包含各类别样本、边界模糊样本、多问题混合样本和纯噪音样本。最开始不需要很大,500张足够评估日常迭代的回归风险。
4.2 第二步:设计三层漏斗的路由逻辑
我的默认架构是三层漏斗加一个人工出口。路由判断顺序是这样的:
# 伪代码示例:混合打标路由逻辑 def route_ticket(ticket): # 第一层:规则命中,直接返回 rule_label = match_rules(ticket) if rule_label and rule_confidence(ticket, rule_label) > 0.9: return rule_label, "rules" # 第二层:Embedding相似度,只有高相似才采用 emb_label, emb_score = match_embedding(ticket) if emb_label and emb_score > 0.86: return emb_label, "embedding" # 第三层:LLM兜底 if llm_available(): llm_label, llm_conf = classify_with_llm(ticket) if llm_conf >= 0.6: return llm_label, "llm" # 低置信度进入人工队列 return None, "human_queue" # LLM不可用/超时:直接进人工队列 return None, "human_queue"注意这个伪代码里的两个阈值:规则的confidence阈值、Embedding的score阈值,都得根据评测集实测调。我见过一种更简单的策略:凡是以上任意一层给出的标签与他人工标签不一致的样本,都会被记录下来,定期复盘调整阈值。
4.3 第三步:写Prompt并做多轮评测迭代
Prompt模板在第2.4节已经给出,实际工程里需要做AB对照。我会固定同一批评测集,分别测试三种Prompt变体:
- 变体A:标签定义极简,只有标签名和一句话说明
- 变体B:带正例和易混淆负例
- 变体C:带误判提醒和拒答出口
结果通常会有明显差异。这里必须要小心,样本量小的时候差异可能只是噪声。一个更可靠的做法是在评测集上连续跑三轮,取多数一致性结果作为该变体的最终输出,再比较不同变体间的准确率差。由于LLM分类存在随机性,一次跑出来的结果不能代表真实水平,这个细节很多人忽略。
4.4 第四步:人工回流与主动学习采样
不是所有工单都值得交给模型,学习曲线中人工抽检是必不可少的。抽检策略可以采用“置信度分层采样”:满置信度、高置信度的工单按5%抽检,中等置信度的按20%抽检,低置信度的全量人工审核。低置信度工单往往是模型最容易翻车的地方,也是模型进步最快的养料。
每周把复核结果回流到模板库和Prompt里:规则层补充新出现的强特征表达,Embedding层增加新模板向量,LLM层把新发现的易混淆案例写进Prompt的负例区。这样系统每周都在变强,而不是上线第一周就是巅峰。
5. 常见问题与排查技巧实录
5.1 问题一:规则层误判率极高,怎么办?
误判通常源于规则过宽或优先级冲突。比如工单里出现“timeout”确实命中了“latency_and_timeout”,但如果工单同时说“Completions.create()报timeout错误重试后成功”,用户真正想问的是如何规避超时,而不是服务故障。此时规则应该给“重试成功”“已恢复”“解决了”等词加否定上下文,避免把“过程描述”当成“问题本身”。
排查方法:把规则命中的工单抽样dump出来,看误判集中在哪个规则表达式上,对特定规则加排除词或者拆分成更细的规则。
5.2 问题二:LLM分类局部类别总是混淆?
一方面看标签定义是否分离度高。“api_error”和“usage_guidance”之间就存在大量灰色地带:报错信息确实是API返回的,但原因在用户请求参数不正确。如果你发现两类总是混淆,先不要调Prompt,把混淆矩阵打出来看,确认是哪些具体案例在混,再把这类案例作为负例写进Prompt。
另一方面看是否真的需要拆分标签。如果混淆的高发区是“用户理解问题”和“API报错”,很可能这两个类别在定义上就不该用同一层级的标签体系。可以考虑增加一个复合层字段,例如primary_label=api_error,secondary_label=param_misuse,将冲突信息降级存为属性。
5.3 问题三:某类别样本极少,模型完全不去识别它?
对这种“长尾类目”,光靠Prompt里的定义往往不够。方法有两个:一是把该类别的典型样本直接放进Prompt做few-shot示范,比纯zero-shot有明显效果提升;二是在Embedding层单独为该类目准备一批高质量模板,提升召回概率。长尾类别还有一个策略是“宁可错过,不要错给”——当系统不确定时不贴标签,而不是硬贴出来增加误导。
5.4 问题四:工单到底是单标签还是多标签?
LLM API工单经常是多问题纠缠,比如“调用报错+想退款+顺便问一下容器部署”。对下游来说,有些场景只要主标签就够,有些场景却需要同时知道“出错了”和“要退款”。我的建议是架构上分成主标签和辅助标签:主标签只允许一个,用于路由;辅助标签允许多个,用于统计和跟进。Prompt里明确告诉模型“先定主标签,再列出辅助标签”,比允许它自由输出多个标签要稳定得多。
5.5 问题五:如何评估打标系统的整体效果?
单独的准确率不足以说明问题。我的团队会同时看三个指标:
- 准确率:打标正确数除以自动打标总数,衡量“打出来的标签有多可信”
- 覆盖率:自动打标数量除以工单总数,衡量“自动系统能接管多少”
- 路由有效率:下游在处理完打标工单后反向确认标签是否对处理有帮助,这是更贴近业务价值的指标
实践中一个很反直觉的发现是:有时准确率下降,但路由有效率上升。因为LLM更“敢打”了,覆盖率增加,虽然错了一部分,但更多的正确工单及时流入了正确流程,整体业务收益反而变大。做打标系统不能只看模型指标,要回到下游的业务目标看结果。
5.6 问题六:要不要微调专用分类模型?
如果工单量已经到日万级,且标签体系相对稳定,微调一个小的分类模型确实可能比每次调用外部大模型更划算。但微调模型的前提是,你至少要有几千张高质量人工标注数据。如果做不到这个量级,硬做微调只会得到一个过拟合的低质量分类器。我见过一个折中的路径:先用一个轻量开源模型在现有标注数据上做指令微调,作为规则层的升级替代;LLM API仍然保留,只处理微调模型低置信度的工单。这样既保住了成本,也保住了兜底能力。
6. 最后留个实在的建议
打标这件事,本质是在为组织建立一张“问题地图”。方法只是引子,真正难缠的是让标签对下游有价值、让系统能持续进化。我最终没有迷信任何单一方案,默认架构就是规则做前锋、向量做辅助、LLM做兜底、人工做裁判。任何一层单独承担全局都会出事。
如果你现在正准备做这套系统,我的建议顺序是:先拿一周时间做一轮小样本标注评审,固化标签定义,再按“规则先行、后续叠加”的节奏推进。不要一上来就追求全自动,50%的自动覆盖率已经能让团队从力不从心里缓过一口气了。之后每一条回流数据和每一次阈值调整,都是这个系统生长的痕迹。工程上没有一步到位的完美打标,只有越跑越稳的打标。