模型输出格式错误的工具调用块时,Cindy 静默结束回合,且把泄漏的正文按 LaTeX 渲染成乱码
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 395
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
**提交人**: 匿名
**客户端版本**: 0.1.45
---
## 现象
长会话中偶发:模型本该发起一次工具调用,但该调用块被当成**普通正文文本**输出。结果:
1. 该回合**静默正常结束** —— 无任何报错或提示,工具实际没执行;
2. 泄漏出的正文被 markdown + LaTeX 渲染,变成一堆看不懂的半截英文和居中公式;
3. 用户**无法判断这一步到底做完了没有**,只能靠自己事后发现异常、手打「继续工作」。
主因在模型侧(它的开标签写坏了,transcript 可确认 Cindy 未改写模型输出)。**但 Cindy 侧有两个可修的放大器**,本 issue 针对这两点。
## 复现步骤
实测 423 次正常工具调用中出现 4 次。集中出现在**单次调用参数很长、且内部嵌套引号 / 正则 / 反斜杠**时(如 `python -c "..."` 单行脚本,泄漏正文长 500~1700 字符)。
坏输出分两类,Cindy 处理结果完全不同:
**类 A(1/4)— 外层结构完整,内部属性名写重**(形如 `name="parameter name="command"`)
→ Cindy **已正确处理**:注入 `Your tool call was malformed and could not be parsed. Please retry.`,模型下一条立即重发成功,用户全程无感。**这个机制是好的。**
**类 B(3/4)— 开标签的 `<` 与外层函数调用标签一起丢失**:形如 `invoke name="Bash">` 开头没有 `<`、也没有外层标签,而紧跟其后的 `` 反而带着 `<`。
→ 解析器从未进入工具调用状态,于是判定为「一个纯文本回合正常结束」:**不报错、不重试、回合终止**。
## 期望行为
**1) 把类 A 已有的检测扩展到类 B。** 若 assistant 的**正文 text**中出现 `invoke name=`、`parameter name=` 等工具调用专用标记,应判定为格式错误的工具调用,走与类 A 相同的 retry 注入路径。实测这能自动救回 3/3。
**2) 至少给出可见提示。** 即使不自动重试,也应标出「⚠ 模型输出了格式错误的工具调用,未执行」,而不是伪装成正常完成的回合 —— 当前用户没任何手段区分「做完了」和「压根没跑」。
**3) 不要对这类内容做 LaTeX 渲染。** 这一条独立于工具调用泄漏也是 bug —— 正常回答里只要出现下列写法就会被误渲染:
| 输入 | 实际渲染 | 说明 |
|---|---|---|
| `(\d{4})(\d{2})` | `(\d4)(\d2)` | `{4}` 被 LaTeX 当分组吃掉 |
| `\[1001\]` | 居中的大号 `1001` | `\[...\]` 被当行间公式定界符 |
讨论正则、转义、模板语法时踩中概率不低。建议:反引号 / 代码块外的 LaTeX 定界符识别更保守,或对含工具调用标记的段落强制等宽 verbatim 显示。
## 实际行为
类 B 下回合静默终止,内容被渲染成乱码,用户无法判断完成状态。
## 复现频率
约 0.9%(4/423 次工具调用);其中 3 次未被任何机制捕获。长会话 + 长参数调用时明显更容易触发。
## 已尝试
用户侧:只能事后肉眼发现异常、手动要求继续 —— 无法预防,也没有提示可依据。
模型侧规避(有效但属于绕过):不再用长单行内联脚本,改为先写脚本文件再执行,缩短单次调用长度、避免嵌套引号。这能降低触发率但无法消除,且 Cindy 侧缺少兜底这一点不变。
## 补充
本文未包含任何日志原文、文件路径或业务代码,标记名已去具体化,仅描述结构形态。
---
**版本区域**: CN
**OS**: win32 x64 (10.0.26100)
**界面语言**: zh-CN
Contributor guide
Research direction
Start by tracing the tool-call parser and the assistant message path that decides whether a turn completed normally. Reproduce both malformed invoke/parameter forms, then inspect the markdown and LaTeX rendering path for leaked tool-call text. Done means malformed calls are detected or visibly reported, retry behavior is preserved where applicable, and leaked markers are not rendered as LaTeX.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- ai, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100