[Bug] 多轮对话生成在并发+同一chunk配置多个GA时,偶发返回字面意义上的空 {"content": ""}
Bug反馈:多轮对话生成在并发+同一chunk配置多个GA时,偶发返回字面意义上的空 {"content": ""}
项目:https://github.com/ConardLi/easy-dataset
版本:1.7.3(桌面客户端)
与 #767 的关系:相关但不是同一个bug。#767 描述的是无论并不并发,chunkContent 在多轮对话第2轮起都会被确定性地初始化成空字符串,导致模型给出的回复"正常但脱离原文"(要么说资料未提及,要么可能编造细节)。本issue描述的是另一个独立问题:只在并发>1、且同一个chunk配置了多个GA同时生成对话时才会触发,表现为模型调用返回字面意义上完全为空的内容,直接导致该轮及后续轮次全部损坏,属于更严重的崩溃型问题。
问题描述
在多轮对话生成任务中,当并发数设置大于1、并且同一个chunk配置了多个GA(体裁受众)变体(即会从同一份chunk并发生成多段各自独立的多轮对话)时,部分(不是全部)并发运行中的对话线程会从某一轮开始,收到字面意义上为空的返回内容 {"content": ""},而同一批次里从其他chunk并发生成的对话不受影响、能正常跑完。一旦某个对话线程触发这个空内容,后续所有轮次也都会持续返回空内容,同时配套的"下一轮问题生成"步骤,由于在对话历史里看不到任何新信息,会反复生成跟上一次几乎一模一样的问题,导致该对话在剩余轮次里退化成"重复问题+空回答"的循环,直到跑满设定轮数。
把并发数设为1可以完全避免这个问题(已验证:删除受影响的对话,用相同的chunk/GA组合、并发数=1重新生成,全部对话成功跑完、没有出现空轮次)。
复现步骤
- 上传一份文档,完成清洗和分块(单个chunk即可复现)。
- 在项目里配置3个GA(体裁受众)变体,这样同一个chunk会被并发生成3段各自独立的多轮对话。
- 在多轮对话生成任务设置里,把并发数设为4(或任意大于1的值)。
- 对这个chunk生成多轮对话(6轮)。
- 观察现象:3个GA对应的对话里,可能有1-2个从某一轮开始(我们的测试中大约是第4轮起)返回空内容,而同一批次里并发跑的其他对话能正常跑完全部轮次。
- 用完全相同的配置(同一chunk、同样3个GA、同样轮数)把并发数改成1重新生成:全部3段对话都能成功跑完,没有空轮次。
服务端日志证据(llama.cpp / LM Studio后端,OpenAI兼容接口)
并发数=4时,日志显示3-4个不同的对话线程在并发的slot之间交替处理(符合预期)。对于受影响的对话,模型返回的内容持续稳定地是:
{
"content": "```json\n{\n \"content\": \"\"\n}\n```",
"reasoning_content": "",
"tool_calls": []
}且每次失败调用的 completion_tokens 都稳定在极低的水平(约15个token)——也就是说模型每次都是稳定、完整地生成了这个固定的空JSON,不是生成到一半被截断。这跟"模型在这次调用里收到的参考资料变量本身是空的/缺失的"这个情况高度吻合(可参考 #767 中关于这段代码chunkContent处理的根因描述),叠加了一个运行时状态竞争问题——似乎存在一个共享/全局的"当前chunk内容"引用,在多个并发跑在同一个chunk上的生成任务之间被读取或清空,而不是每个对话生成任务各自独立持有一份。
配套的"下一轮问题生成"步骤,看到对话历史里上一轮助手没有提供任何新信息,就会重新生成一个跟上一个问题几乎完全相同的问题,导致最终数据集里出现2-3次几乎一字不差的重复提问,直到轮数用完。
同一批次里从不同chunk并发生成的对话没有受到影响,这也是我们怀疑这个共享状态是按chunk级别作用域的(多个针对同一chunk的GA生成任务并发读写),而不是一个泛泛的"并发数量对模型速度"问题的原因。
影响
- 任何在并发数>1、且同一chunk配置了多个GA的情况下生成的多轮对话数据集,都可能悄无声息地包含"跑到中途退化成空轮次/重复轮次"的对话,且不逐条查看原始messages字段是发现不了的。
- 用这些数据构建的下游训练集,需要额外增加自动化后处理步骤,检测并丢弃/截断受影响的对话。
- 用户实际上没法安全地用更高并发数换取更快的生成速度——只要涉及多轮对话生成,就必须被迫退回并发数=1这种较慢的配置,才能规避这个问题。
建议排查方向
- 检查多轮对话生成这部分代码(与 #767 提到的同一区域——
getAssistantReplyPrompt/getNextQuestionPrompt)里,是否存在某个共享的/全局的/模块级别的"当前chunk内容"或类似状态,会被多个并发执行的生成任务读写,而不是作为一个正确作用域隔离的参数/闭包传给每一个对话生成任务。 - 如果确认存在,建议让每个并发的生成任务持有自己独立的一份chunk内容和对话状态副本,而不是持有一个可能被同一chunk上其他并发任务修改的共享引用。
环境信息
- Easy Dataset 1.7.3
- 操作系统:[Windows/Linux]
- 浏览器:[EDGE]
- 后端模型服务:LM Studio(llama.cpp),OpenAI兼容
/v1/chat/completions接口 - 模型:Ornith-1.5-35B-A3B(Q8_0 GGUF);Qwen3.6-35B-A3B(Q8_0 GGUF)上也观察到过但频率较低——问题应该与具体模型无关,更多跟耗时/并发时机有关
- 多轮任务设置:6轮,每个chunk配置3个GA,并发数=4(复现问题) vs 并发数=1(未复现,已通过重新生成验证)
Source: ConardLi/easy-dataset