← 数据分析 Agent

用大模型批量给上万条评论打标签,怎么保证结果不错位?

高频 中等 第 6 / 18 题 更新于 2026/09/27
数据分析Agent批量处理情感分析结构化输出数据质量
学习 AI 实战项目

简化版

上万条评论一条调用一次,成本和时间都扛不住,所以要按批交给模型。批量的风险是错位:模型偶尔少返回一条、把两条合成一条,或者顺序调换,之后每一条结果都挂到了错误的评论上,而且不会报错。解决办法是让每条输入带 ID、要求模型原样带回,返回后代码做三项校验:是数组、长度与本批一致、每个位置的 ID 与输入同位置一致。任何一项不通过就整批重发一次,仍不通过就整批放弃并记入排除名单,不去猜哪条对哪条。已成功的结果落库,重跑时跳过,失败的批次不会被反复取到。

详细版

取一批(批大小来自配置,比如 20 条):
  [{"id": 101, "text": "..."}, {"id": 102, "text": "..."}, ...]
  → 模型按固定格式返回:
  [{"id": 101, "sentiment": "正面", "score": 0.86}, {"id": 102, ...}, ...]
  → 代码校验:
       ① 是 JSON 数组
       ② 长度 == 本批条数
       ③ 第 i 个元素的 id == 输入第 i 条的 id
     全部通过 → 逐条落库
     任一不通过 → 整批重发一次 → 仍不通过 → 整批记入排除名单,本轮不再取
  → 取下一批:跳过已处理的,排除名单里的不取
风险表现对策
少返回20 条返回 19 条长度校验
合并 / 拆分两条评论合成一个结果长度校验 + ID 逐位比对
顺序调换第 3、4 条结果互换ID 逐位比对
格式不对返回一段文字而不是数组数组校验 + 输出解析
反复失败同一批每次都校验不过重发一次后放弃,记入排除名单

完整版教学

一、为什么要按批,又为什么批量会出问题

一万多条评论,逐条调用意味着一万多次请求:耗时长,还会触发接口限流,费用也高(每次都要重复发送系统提示词)。按批处理,比如一次 20 条,调用次数降到几百次。

但批量带来一个新问题:模型的输出和输入之间没有天然的对应关系。逐条调用时,返回结果一定属于那条输入;批量调用时,第 5 个结果是不是第 5 条评论的,只能靠模型「自觉」。一旦模型少给一条,后面的所有结果都往前错一位,第 6 条评论的情感被写到了第 5 条上——数据库里的数据全部错了,却没有任何报错。

记忆钩子:批量调用最危险的不是失败,而是「成功地错位」。

二、输入带 ID,输出带回 ID

对齐的第一步是给每条输入一个 ID,并在 Prompt 里要求模型原样带回:

请对以下评论逐条判断情感,按输入顺序返回 JSON 数组,
每个元素包含 id(与输入相同)、sentiment(正面/中性/负面)、score(0~1)。
不要合并、跳过或调换顺序。

输入:
[{"id": 101, "text": "特效很震撼,剧情有点拖"},
 {"id": 102, "text": "看睡着了"}]

ID 用系统里的真实主键,不要用 1、2、3 这样的序号——序号在不同批之间会重复,也无法和数据库对上。

三、三项校验缺一不可

返回后,代码按顺序校验:

校验拦住的问题只做这一项会漏掉什么
是数组返回一段文字、JSON 不完整数组里的内容是否对齐
长度一致少一条、多一条、合并、拆分漏一条又拆一条、顺序调换
同位置 ID 一致顺序调换、错位需与前两项一起才完整
① 是数组          解析失败或不是数组,说明格式不对
② 长度一致        少了或多了,说明有合并、拆分或遗漏
③ 同位置 ID 一致  逐个比对第 i 个结果的 id 和第 i 条输入的 id

为什么只校验长度不够?长度一致不代表对齐:模型可能漏掉第 3 条、又把第 7 条拆成两条,长度恰好不变。为什么要求同位置一致,而不是按 ID 重新匹配?按 ID 匹配看起来更宽容,但模型在重排、合并时往往伴随内容混乱(把 A 的判断写到 B 的 ID 下),严格要求位置一致能更早发现问题。

四、失败了怎么办:重发一次,然后放弃

校验不通过时的处理:

第一次不通过 → 整批原样重发一次(模型的错位多是偶发,重发通常就对了)
第二次仍不通过 → 整批放弃,这批 ID 记入本轮的排除名单

关键原则是不猜:不要尝试「长度少了一条,那就把能对上的先存了」,你无法确定哪几条是对的。宁可少处理一批,也不写进错误的数据。

排除名单必须存在:下一次取批时如果不排除这些 ID,取到的还是同一批,循环永远跑不完。取数 SQL 里用 not in (...) 排除它们,名单为空时这一段不拼(not in () 是语法错误)。

五、断点续跑:成功的不重做

批量任务常常中途失败(服务重启、额度用完)。要支持续跑:

每批通过校验后立即落库,而不是全部跑完再统一写
取下一批时只取「尚未处理」的记录,按 ID 升序分段取,不漏不重
重跑任务时,已处理的自动跳过,从上次停下的地方继续

这样即使任务中途失败,之前已处理好的结果依然有效,不需要从头再来。

六、每次调用都要记日志

包括重发的那一次,每次模型调用都写一条日志:批次号、条数、耗时、Token、是否通过校验、失败原因。这样能统计出:

首次通过率:模型在这个批大小下有多稳定
重发成功率:重发一次能挽回多少
放弃批次数:有多少数据最终没有处理

如果首次通过率偏低,通常说明批太大了,可以调小批大小(放在配置里调整,不改代码);也可能是某类文本(超长、含特殊字符)容易让模型出错,可以针对性处理。

七、多阶段加工要分开

评论加工常常不止一个任务:先做情感分析,再抽取维度标签(比如剧情、演技、特效、节奏、视听)。建议分成独立的阶段、分别调用:

阶段一:情感(正/中/负 + 分数)
阶段二:维度标签(每个维度的评价倾向)

每个阶段有自己的「待处理」判定和排除名单,一个阶段失败不影响另一个阶段已有的结果;Prompt 也更短更专注,模型更不容易出错。

八、常见误区与追问

  • 误区:长度一致就说明对齐了。 漏一条又拆一条时长度不变,必须逐位比对 ID。
  • 误区:校验失败时,把能对上的先存下来。 无法确定哪几条是对的,应该整批重发,仍失败就整批放弃。
  • 误区:失败就一直重试到成功。 同一批反复失败,多半是内容本身让模型出错,重发一次后放弃并记入排除名单。
  • 误区:用 1、2、3 这样的序号当 ID。 序号在批之间重复,也无法对应数据库,应该用真实主键。
  • 误区:全部跑完再统一落库。 中途失败会丢掉所有结果,应该每批通过后立即落库,支持断点续跑。
  • 追问:批大小怎么定? 放在配置里,根据首次通过率调整:通过率低就调小。
  • 追问:中途失败了,已经加工好的还算数吗? 算,成功的已经落库,续跑时跳过;只有两次都没通过的那批被排除。

九、加强记忆

上万条评论要按批处理,但批量最怕「成功地错位」:少一条、合并、调换顺序都不会报错。对策是输入带真实主键 ID 并要求原样带回,返回后校验三项:是数组、长度一致、同位置 ID 一致。任一不通过整批重发一次,仍不通过整批放弃并记入排除名单,绝不猜哪条对哪条;排除名单保证不会反复取到同一批。每批通过后立即落库,按 ID 升序分段取,支持断点续跑。每次调用都记日志,用首次通过率调整批大小。多阶段加工分开调用,互不影响。