From 1fdbc7353fad731bf1f5bcedc2b434d77a1a9ee4 Mon Sep 17 00:00:00 2001 From: ssurui Date: Mon, 5 Oct 2026 17:06:14 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E8=AE=B0=E5=BD=95=E6=8E=AA=E8=BE=9E?= =?UTF-8?q?=E5=BC=95=E5=AF=BC=E8=AF=AD=E4=BD=8D=E7=BD=AE=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E8=AF=AF=E5=88=A4"=E6=9F=A5=E4=B8=8D=E5=88=B0"=E7=9A=84?= =?UTF-8?q?=E7=9C=9F=E5=AE=9E=E8=B8=A9=E5=9D=91=E4=B8=8E=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 补充 withToneHint() 的插入位置问题:追加在提示词末尾会让这条本该 "仅在没有足够信息时才用"的条件引导,变成模型倾向主动找机会使用的 独立指令,真机复测连续3次有1次把有效答案误判成"查不到"。记录修复 方式(嵌入原条件分句内部)和验证方法论的教训(测试必须走完整调用链, 不能绕开直接测生成接口)。 Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01QeoAy5KmkHuKWHAktpEsaN --- CLAUDE.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 22d41e9..71212f3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -208,10 +208,14 @@ const vectors = await Promise.all(texts.map((t, i) => fetchOne(t, i))) 提示词要求"说明手册中暂未查到,并给一条可操作的建议",而不是硬邦邦一句"我不知道"。 -**光在提示词里写"每次换一种措辞"是无效的**——模型每次请求都是无状态的,不知道上次说了什么,实测同样输入连发三次答复一字不差,而且会照抄提示词里给的示例。所以措辞变化由代码侧提供:`generator.ts` 的 `withToneHint()` 每次请求随机挑一条引导追加到系统提示词末尾,让输入本身产生差异。 +**光在提示词里写"每次换一种措辞"是无效的**——模型每次请求都是无状态的,不知道上次说了什么,实测同样输入连发三次答复一字不差,而且会照抄提示词里给的示例。所以措辞变化由代码侧提供:`generator.ts` 的 `withToneHint()` 每次请求随机挑一条引导,让输入本身产生差异。 **没有采用调高 temperature 的做法**:那会同时影响命中文档的正常回答,而维修手册问答更看重稳定准确。 +**`withToneHint()` 的插入位置踩过一次真实的坑**:第一版把引导语整句追加在系统提示词最末尾(紧邻用户问题,模型注意力权重最高的位置)。真机复测发现:同一个检索到充分相关内容、理应直接作答的问题,连续追问 3 次,有 1 次被模型硬套上"手册里未查到…"的开场白,即便后面还是照常给出了详细步骤——答案读起来却像没查到,用户也确实这样反馈过。根因是这条指令脱离了它原本所属的"仅在没有足够信息时才用"的条件分句,变成了提示词末尾一条独立显眼的指令,模型会倾向"找机会用上它"。**现在改为把引导语嵌入到原本那条"如果没有足够信息"分句内部**(`NO_MATCH_BULLET_MARKER` 定位插入点,在 `config.ts` 的默认提示词里找 `以便更准确地定位;` 这句),位置和从属语气都跟原本不带随机性的版本保持一致。用户在设置页改写过这句话、不含该标记时,`withToneHint()` 原样返回不插入,不强行拼接导致语义错位。 + +**排查这个 bug 时的一个教训**:之前测试这个功能时没能发现问题,是因为测试脚本直接拿纯净的 `systemPrompt` 调用生成接口,没有复现 `withToneHint()` 在真实请求里的行为——以后验证跟 prompt 拼接相关的改动,测试必须经过完整的 `streamGenerate()`/`withToneHint()` 调用链,不能绕开直接测底层生成接口。 + 另外,`queryHandler`/`visionHandler` 里 `chunks.length === 0` 的兜底文案说的是"知识库还没有文档,请先导入"而不是"我不知道"——`search()` 是全表余弦排序后截断,只要库里有文档就一定返回结果,走到那个分支只可能是库为空。 ### Vue Proxy IPC 序列化