Replies: 1 comment
|
你的诊断我们从另一条路由做了 A/B 实测,结论既佐证了你的定位、也给了一条今天就能用的活路: 同样被污染的历史(助手消息文本里带被 两个含义:
边界说明:我们注入的是单个孤立高代理的最小形态;你日志里的具体字节序列若有别的变体,以你的复现为准。 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
摘要
当会话历史中出现孤立 Unicode 代理项(例如一行文本被 JS
String.prototype.slice()按 UTF-16 码元截断,把 emoji 🔍 U+1F50D 的代理对\ud83d\udd0d拦腰切断、只保留高代理\ud83d)时,deepseek-official适配器(dsh-llm-deepseek)会把它原样序列化进请求体,DeepSeek API 的严格 JSON 解析器随即以 HTTP 400 拒绝整个请求。由于该字符永远留在历史里,该会话从此所有请求(包括之后新开的 turn)确定性失败;新建会话则完全正常。且 400 响应体不是标准错误信封,客户端只能看到通用的DeepSeek API error (HTTP 400),无法自行定位。环境
@deepseek-ai/dsh0.1.0-rc.6,Web GUI 模式;适配器包dsh-llm-deepseek)deepseek-official,请求直达https://api.deepseek.com/chat/completionsdeepseek-v4-flash(deepseek-v4-pro走同一 API/解析器,应同理——未实测)thinking: {type:"enabled"}、reasoning_effort: "max"、max_tokens: 256000、stream: true—— 这些参数本身均被官方 API 接受(已实测 200)现象
HTTP 400,错误文案为通用的DeepSeek API error (HTTP 400),codeINVALID_REQUEST,无任何服务端细节。\ud83d(位于表格行...| Docker 任务自动触发 | \ud83d处)。根因(已逐层实测验证)
run_code程序(模型编写)对 grep 结果逐行执行m.line.slice(0, 120)。JS 字符串按 UTF-16 码元切片,而行内 emoji🔍(U+1F50D =\ud83d\udd0d)恰好跨越第 119/120 个码元:slice(0,120)只保留高代理\ud83d,丢掉低代理\udd0d→ 输出孤立代理项。slice(0,120)必中(119 < 120 < 121)。dsh-session-persistence-jsonl)按 UTF-16 码元保留孤立代理项(源码注释明确 "Operating on code units preserves lone surrogates");dsh-llm-deepseek的serializeMessages/serializeRequest直接JSON.stringify,无消毒。JSON.stringify把孤立代理项输出为"\ud83d"转义序列;DeepSeek API 的严格 JSON 解析器拒绝该转义 →HTTP 400。Failed to parse the request body as JSON: ...(不是 OpenAI 风格{"error":{"message":...}}信封),适配器index.js中(await response.json()).error解析失败,回退到通用文案DeepSeek API error (HTTP 400),用户无法定位。最小复现(已实测)
\ud83d即 NodeJSON.stringify对孤立高代理的标准转义,也就是 DSH 适配器实际发送的内容。① 的复现同样在携带thinking/reasoning_effort/max_tokens:256000/stream参数时成立。建议修复
Harness 侧(本仓库)
dsh-llm-deepseek序列化前将孤立代理项(未配对的U+D800–U+DFFF)替换为U+FFFD,与仓库内已有先例一致(dsh-tool-cordis按 code point 截断、dsh-host-apiproxy导出时避开代理对边界)。DeepSeek API error (HTTP 400): <body 前 200 字符>),此类解析错误即可秒定位。API 侧(可另报 DeepSeek API 平台)
4. JSON 解析类 400 也返回标准错误信封
{"error":{"message":...}},让客户端能向用户展示真实原因。用户侧规避
5. 在工具程序里截取含 emoji 的文本时勿用 JS
.slice()(按码元),改用按 code point 截断(如Array.from/Intl.Segmenter);若会话突然全部 400,先检查最近工具结果里是否有\uD800-\uDFFF转义。验证记录
\ud83d→ 400(错误原文如上);②对照组 → 200(同参数)。两者均真实调用官方 API。\ud83d;随后 turn 4–12(12:40–12:45)全部在 step 1 即 400(共 10 个失败 turn)。slice(0,120)必切中),证明毒字符产生于程序内切片而非文件损坏。附件(路径已脱敏)
~/.dsh/sessions/**/session-516482a7-*/session.jsonl.zstd...| Docker 任务自动触发 | \ud83d(后续为换行与下一行| akshare-stock | ...)All reactions