1. 为什么“不训练”这件事值得认真聊文本分类算是自然语言处理里最接地气的任务之一了。情感分析、工单路由、内容审核、意图识别本质上都是把一段文本映射到一个预设的类别标签上。过去几年做文本分类的标准路径非常清晰标注数据、选一个预训练模型比如BERT这类、微调、评估、上线。这套流程成熟、稳定效果也可控但它有一个绕不开的前提——你得有标注数据。标注数据的成本做过的人心里都有数。一个三分类任务每个类别想达到基本可用的效果少说也得几百条标注样本类别越多、边界越模糊需要的量就越大。更麻烦的是业务场景经常变今天加一个类别明天改一个定义标注工作就得重来一遍。很多小团队或者个人开发者卡就卡在这一步模型还没开始调标注的活已经把人耗干了。Zero-Shot 分类的出现正好戳中了这个痛点。它的核心承诺很诱人不训练、不标注直接拿一个大语言模型给它一段文本和一组候选标签让它告诉你这段文本属于哪一类。听起来像是白嫖但实际用下来你会发现它既有让人惊艳的优雅之处也有不少容易踩的坑。这篇就围绕“不训练也能分类”这个主题把 Zero-Shot 文本分类的底层逻辑、实操方法、参数选择、常见问题和避坑经验尽量掰开揉碎讲清楚。需要先说明一点这里的“不训练”指的是不做针对性的模型微调而不是说模型本身没经过训练。我们用的还是那些在海量语料上预训练过的大语言模型只是不再用标注数据去调整它的参数。理解这个前提后面很多现象就说得通了。这篇文章适合几类人看一是手上没有标注数据、又想快速验证分类可行性的开发者二是已经在用大模型做分类、但效果忽好忽坏想找原因的人三是对 Zero-Shot 能力边界好奇、想搞清楚它到底能干什么不能干什么的技术爱好者。不管你是哪一类下面的内容都会尽量给出可以直接上手操作的方案而不是停留在概念层面。2. Zero-Shot 文本分类的整体思路拆解2.1 它到底是怎么“不训练”就完成分类的要理解 Zero-Shot 分类得先理解大语言模型在预训练阶段学到了什么。简单说模型在海量文本上见过太多“什么话在什么语境下出现”的规律它内部已经形成了一套相当强的语义理解能力。当你给它一个任务描述和一组候选标签时它其实是在做一件事判断哪個标签和当前文本的语义最匹配。举个生活化的类比。假设你从来没学过医学但你读过大量书对“发烧”“咳嗽”“骨折”“过敏”这些词的含义和常见搭配都有概念。现在有人给你一段描述“患者持续高热三天伴有干咳和乏力”然后问你这段描述最接近上面哪个词。你不需要专门去学医凭语义直觉就能选“发烧”。Zero-Shot 分类就是这个逻辑模型靠的是预训练阶段积累的语义关联而不是针对你这个具体任务学到的判别边界。具体到实现上常见的有两种路子。一种是基于自然语言推理NLI的思路把“文本属于某类别”转化成一个推理问题比如“前提这段文本是XXX假设这段文本属于‘投诉’类别”然后让模型判断这个假设是否成立。另一种更直接就是基于生成或打分的思路把候选标签直接放进提示词里让模型输出最匹配的标签或者对每个标签给出一个概率/分数。两种路子各有优劣后面会细说。2.2 为什么它优雅三个让人心动的点Zero-Shot 最直接的优雅之处就是零标注成本。你不需要准备任何训练数据只要把类别定义写清楚马上就能跑起来。对于快速验证一个想法、或者处理长尾类别这个优势是压倒性的。我试过在一个全新的业务场景里从零开始到拿到第一版分类结果前后不到半小时这在微调时代是不可想象的。第二个优雅点是灵活性极高。类别可以随时增删改不需要重新训练。今天业务说要多加一个“退款咨询”类别你只需要在提示词里加一行标签定义立刻就能用。这种动态调整能力在需求变化快的场景里非常实用。微调模型改类别意味着要重新准备数据、重新训练、重新评估周期至少按天算Zero-Shot 改类别按分钟算。第三个优雅点是冷启动友好。很多垂直领域根本没有公开的标注数据集自己标又太贵。Zero-Shot 让你在没有数据的情况下也能先跑出一个基线哪怕效果只有七十分也足以支撑早期的产品验证和流程跑通。有了这个基线后续再决定要不要投入资源做微调决策就有了依据。2.3 陷阱藏在哪三个容易被忽视的问题优雅归优雅Zero-Shot 的陷阱也不少而且很多是用了之后才会暴露出来的。第一个陷阱是类别定义的敏感性。Zero-Shot 分类的效果很大程度上取决于你怎么描述类别。同一个类别换个说法结果可能差很多。比如“投诉”这个类别你写成“用户表达不满”和写成“用户对产品或服务提出负面反馈并要求解决”模型的理解可能就不一样。更麻烦的是当类别之间有语义重叠时模型很容易混淆。比如“咨询”和“求助”在很多语境下边界模糊模型可能一会儿选这个一会儿选那个。第二个陷阱是标签数量的影响。候选标签越多模型要做的区分就越细准确率通常会下降。我实测过一个场景三分类的时候准确率能到八成多加到八分类就掉到六成左右。这不是模型不行而是任务本身变难了。所以 Zero-Shot 更适合类别少、边界清晰的场景类别一多就得考虑其他方案。第三个陷阱是评估的困难。因为没有标注数据你很难客观判断 Zero-Shot 的效果到底怎么样。你看到的几个例子效果好不代表整体就好你看到的几个例子效果差也不代表整体就差。没有评估集调优就变成了盲调。这个问题在后面会专门讲怎么缓解。3. 核心细节解析与实操要点3.1 提示词怎么写类别描述的三个层次提示词是 Zero-Shot 分类的核心写得好不好直接决定效果。我把类别描述分成三个层次从简到繁效果通常也是递增的。最简层次是只给标签名。比如候选标签就是“正面”“负面”“中性”提示词里只列这三个词。这种方式最省事但模型对类别的理解完全依赖它自己的先验知识遇到领域特定的类别就容易跑偏。中间层次是标签名加简短说明。比如“正面表达满意、赞扬或推荐”“负面表达不满、批评或抱怨”。加一句说明相当于给模型划了一个大致范围效果通常会有明显提升。这个层次的性价比最高大多数场景下够用了。最高层次是标签名加详细定义加边界说明加示例。比如“投诉用户对产品或服务表达明确不满通常包含要求解决、赔偿或改进的诉求。注意与‘咨询’区分咨询是询问信息不包含不满情绪。示例‘我买的这个用了两天就坏了你们怎么处理’”。这种方式效果最好但提示词会变长推理成本也会上升。适合类别边界模糊、对准确率要求高的场景。提示类别说明不是越长越好。我试过把每个类别的说明写到两百字结果模型反而更容易被无关信息干扰。一般来说每个类别一到两句话把核心边界说清楚就够了。3.2 标签设计怎么让模型更容易区分标签设计有几个实操要点都是踩过坑之后总结出来的。第一标签之间要尽量互斥。如果两个类别在语义上高度重叠模型很难稳定区分。遇到这种情况要么合并类别要么在说明里明确划出边界。比如“物流慢”和“服务差”如果业务上确实要分开就得说清楚“物流慢特指配送时效问题服务差特指客服态度问题”。第二标签名用业务语言不用技术语言。模型对日常用语的语义理解通常比对专业术语更准。比如“情感倾向”不如直接写“正面/负面”“意图类别”不如直接写“咨询/投诉/购买”。标签名越接近自然语言模型越容易理解。第三标签数量控制在合理范围。根据我的经验Zero-Shot 在五分类以内效果比较稳超过十个类别就要谨慎了。如果业务上确实需要很多类别可以考虑分层分类先粗分几个大类再在每个大类下细分。这样每一层的标签数量都不多模型更容易处理。第四给标签排个序。有些模型对标签顺序敏感把更常见或更重要的类别放在前面有时能提升效果。这个不是绝对规律但值得试一下。3.3 输出格式怎么让结果更稳定Zero-Shot 分类的输出格式直接影响结果的可解析性和稳定性。常见的做法有几种。最简单的是让模型直接输出标签名。提示词里写“请只输出最匹配的类别名称不要输出其他内容”。这种方式解析简单但模型有时会不听话多输出一些解释性文字。更稳的是让模型输出结构化结果比如 JSON 格式包含标签和置信度。这样解析起来更可靠也能拿到模型的置信度信息。不过要注意模型给出的置信度不一定校准得很好只能作为参考不能完全当真。还有一种做法是让模型对每个标签打分然后取最高分。这种方式能拿到更细粒度的信息但推理成本会上升因为要对每个标签单独跑一次或者让模型一次性输出所有分数。适合对可解释性要求高的场景。注意不管用哪种输出格式都要在代码里做容错处理。模型偶尔会输出格式不对的内容或者输出一个不在候选列表里的标签。这些情况都要有兜底逻辑不能让程序直接崩掉。3.4 温度参数别让模型太“有创意”温度参数控制模型输出的随机性。做分类任务时我们希望模型稳定、确定所以温度要设低通常设成 0 或者接近 0 的值。温度高了模型可能会给出一些出人意料的答案这在创意写作里是好事在分类里就是灾难。我试过同一个输入温度设 0.7 的时候模型在几个类别之间来回跳设成 0 之后结果就稳定多了。所以做分类温度一律往低了设这是基本操作。4. 实操过程与核心环节实现4.1 环境准备与模型选择动手之前先要把环境搭起来。Zero-Shot 分类对硬件的要求取决于你用什么规模的模型。如果调用的是在线 API那基本不需要本地算力有网络就行。如果要在本地跑开源模型那就要看模型大小了。七B参数级别的模型量化之后消费级显卡就能跑更大的模型就需要更多显存。模型选择上有几个考量维度。通用能力方面参数越大的模型通常语义理解越强Zero-Shot 效果也越好但成本和延迟也越高。领域适配方面如果任务涉及特定领域选一个在该领域语料上训练过的模型会更有优势。响应速度方面如果要做实时分类就得在效果和速度之间做权衡。我的建议是先用一个中等规模的模型跑通流程看看效果能不能接受。如果能接受再考虑要不要换更大的模型提升效果如果不能接受再分析是提示词的问题还是模型能力的问题对症下药。4.2 一个完整的分类流程示例下面用一个虚构的场景来演示完整流程。假设我们要做一个用户反馈分类类别有四个咨询、投诉、建议、其他。第一步写提示词。提示词的结构大概是任务说明加类别定义加输出格式要求加待分类文本。任务说明写“你是一个文本分类助手请根据下面的类别定义判断用户反馈属于哪一类”。类别定义按前面说的中间层次来写每个类别一句话说明。输出格式要求写“请只输出类别名称”。第二步准备测试样本。因为没有标注数据我通常会手工构造一批覆盖各种情况的样本比如每个类别准备五到十条再加上一些边界模糊的样本。这批样本不用于训练只用于观察模型行为。第三步跑一遍看结果。把样本逐条喂给模型记录输出。然后人工看一遍哪些对了哪些错了错的原因是什么。这一步很关键能帮你快速定位问题。第四步迭代提示词。根据错误案例调整类别说明或者调整输出格式然后再跑一遍。通常迭代两三轮效果就会有明显改善。第五步小规模验证。如果条件允许找业务方人工标注一小批真实数据哪怕只有几十条用来做客观评估。这比完全靠感觉调优要靠谱得多。4.3 参数选择与成本估算Zero-Shot 分类的主要成本是推理成本。如果调用在线 API成本跟输入输出长度、调用次数有关。提示词越长单次调用越贵类别越多、样本越多总调用次数越多。控制成本有几个办法。一是精简提示词把不必要的说明删掉只保留核心信息。二是批量处理如果 API 支持一次传多条文本就批量传减少调用次数。三是缓存结果同样的输入没必要重复调用。四是分级处理先用小模型或简单规则过滤掉明显简单的样本只把难的样本交给大模型。延迟方面如果做实时分类单次调用延迟要控制在可接受范围内。提示词越长、模型越大延迟越高。必要时可以考虑异步处理或者预计算。4.4 结果后处理与兜底策略模型输出不能直接信要有后处理。最基本的后处理是格式校验输出是不是在候选标签列表里如果不是就要走兜底逻辑比如归到“其他”类别或者触发人工审核。更进一步的后处理是置信度过滤如果模型给出的置信度低于某个阈值就认为结果不可靠走人工审核。这个阈值需要根据实际数据调没有通用值。还有一种是多模型投票用两个不同的模型分别分类如果结果一致就采纳不一致就人工介入。这种方式能提升准确率但成本翻倍适合对准确率要求极高的场景。5. 常见问题与排查技巧实录5.1 模型总是选同一个类别怎么办这是 Zero-Shot 分类里最常见的问题之一。模型不管输入什么都输出同一个标签。原因通常有几个。一是类别不平衡在提示词里的体现。如果你在提示词里把某个类别写得很详细其他类别写得很简略模型可能会倾向于选那个详细的类别。解决办法是让各类别的说明长度和详细程度尽量均衡。二是类别定义有重叠。如果某个类别的定义过于宽泛把其他类别的情况也覆盖了模型就会一直选它。解决办法是收紧定义明确边界。三是模型能力不足。如果模型本身语义理解能力有限它可能只能抓住最明显的特征导致所有输入都被归到最显著的那个类别。这种情况换更大的模型通常能缓解。5.2 边界样本怎么处理边界样本是 Zero-Shot 分类的难点。一段文本既像咨询又像投诉模型怎么选都有道理。处理这类样本有几个思路。一是在提示词里明确优先级。比如写“如果文本同时包含咨询和投诉特征优先归类为投诉”。这样模型遇到边界情况就有据可依。二是增加“其他”或“混合”类别。对于确实无法归入现有类别的样本给一个出口避免模型硬选一个不合适的类别。三是接受不完美。Zero-Shot 本来就不是百分百准确的方案边界样本出错是正常的。关键是要知道错在哪里评估影响有多大必要时人工兜底。5.3 效果不稳定怎么排查效果不稳定表现为同样的输入不同时间跑出来的结果不一样或者稍微改一下提示词结果就大变。排查思路如下。先看温度参数。温度是不是设成了非零值如果是先设成零再试。再看提示词。提示词里有没有模棱两可的表述有没有可能被模型理解成多种意思的地方把提示词改得更明确、更结构化。然后看模型版本。如果用的是在线 API模型版本有没有变有些服务商会不定期更新模型更新后行为可能变化。最后看输入长度。输入文本特别长的时候模型可能抓不住重点。可以考虑先做摘要或关键句提取再分类。5.4 常见问题速查表问题现象可能原因排查方向解决思路总是输出同一类别类别定义不均衡或重叠检查各类别说明长度和边界均衡说明收紧定义边界样本反复横跳类别边界模糊检查是否有优先级说明加优先级规则或混合类别结果不稳定温度非零或提示词模糊检查温度和提示词温度设零提示词结构化输出格式不对输出要求不明确检查格式说明明确要求加容错解析类别多了准确率下降任务难度上升统计各类别混淆情况分层分类或减少类别推理成本太高提示词太长或调用太多统计 token 用量精简提示词批量处理提示这张表里的排查方向建议按顺序来。先查最简单的温度、格式再查复杂的类别定义、模型能力。很多时候问题就出在最简单的地方。5.5 几个独家避坑技巧第一个技巧用“反向验证”检查类别定义。写完类别说明后自己构造一些明显属于其他类别的样本看模型会不会误判。如果会说明类别边界没划清楚。第二个技巧保留一份“黄金样本”。手工挑选一批覆盖各种情况的样本每次改完提示词都跑一遍对比结果变化。这能帮你判断改动是变好了还是变差了。第三个技巧别迷信置信度。模型给出的置信度经常偏高明明错了还说自己很有把握。置信度只能作为参考不能作为唯一依据。第四个技巧提示词版本管理。每次改提示词都记下来改了什么、效果怎么变。不然改了几轮之后你自己都忘了哪版效果最好。第五个技巧先粗后细。如果类别很多先做粗分类再做细分类。一次让模型区分十几个类别不如分两层每层区分三四个类别。6. 什么时候该用 Zero-Shot什么时候不该用6.1 适合 Zero-Shot 的场景Zero-Shot 最适合快速验证和冷启动。当你有一个新想法想快速看看可行性Zero-Shot 是最快的方式。不需要标注数据不需要训练几十分钟就能拿到第一版结果。它也适合类别少、边界清晰的场景。三到五个类别每个类别定义明确Zero-Shot 的效果通常够用。比如情感分析的正负中三分类或者简单的意图识别。还适合长尾类别和动态类别。有些类别样本极少标注不划算用 Zero-Shot 处理就很合适。类别经常变的场景Zero-Shot 的灵活性也是优势。6.2 不适合 Zero-Shot 的场景类别多且边界模糊的场景Zero-Shot 效果通常不理想。十几个类别互相重叠模型很难稳定区分。这种场景要么做分层分类要么考虑微调。对准确率要求极高的场景Zero-Shot 也不合适。没有标注数据做评估和调优准确率很难保证。这种场景还是得老老实实标注数据、微调模型。领域专业性极强的场景Zero-Shot 可能力不从心。如果类别涉及大量专业术语和领域知识通用大模型可能理解不到位。这种场景要么用领域模型要么在提示词里补充足够的领域知识。6.3 混合方案Zero-Shot 加少量标注实际项目里纯 Zero-Shot 和纯微调都不是最优解。更实用的做法是混合方案先用 Zero-Shot 跑一版结果人工审核修正把修正后的结果作为标注数据再用这些数据微调一个小模型。这样做有几个好处。一是标注成本大幅降低因为只需要修正 Zero-Shot 的结果不需要从零标注。二是微调后的小模型推理成本低、速度快适合上线。三是 Zero-Shot 的结果可以作为基线用来评估微调模型的效果提升。我试过这个流程在一个四分类任务上先用 Zero-Shot 跑了一千条人工修正了其中约三百条然后用这三百条微调了一个小模型。最终效果比纯 Zero-Shot 提升了十几个百分点而标注成本只有从零标注的三成左右。7. 我个人在实际操作中的几点体会Zero-Shot 分类这件事用一句话总结就是入门容易用好难。跑通一个 demo 可能只要十分钟但要让它在真实业务里稳定可用需要花不少心思调提示词、设计类别、处理边界情况。我最大的体会是提示词工程在 Zero-Shot 分类里的权重比很多人想象的要高。同样的模型提示词写得好和写得差效果可能差出一倍。所以别急着换模型先把提示词打磨到位。另一个体会是评估比调优更重要。没有评估调优就是盲调。哪怕只有几十条人工标注的评估样本也能让你的调优有方向。我现在的习惯是任何 Zero-Shot 项目开始之前先花时间构造一批评估样本后面所有改动都拿这批样本对比。最后分享一个小技巧把类别定义写成“给新同事解释”的口吻。想象你在给一个刚入职的同事解释这个类别是什么意思怎么说他才能听懂。这种口吻写出来的定义通常模型也更容易理解。这个技巧我用了很多次效果一直不错。Zero-Shot 不是银弹但它确实打开了一扇门在没有标注数据的情况下也能先把事情跑起来。至于跑起来之后怎么优化那就是另一个话题了。