报错是这么冒出来的。前端用 mustache 1.0 渲染 prompt 模板,模板里写 {{#context}}{{text}}{{/context}},浏览器里整段被 markdown 渲染器当成 HTML 注释吞掉,发给模型的 prompt 少了上下文,回答一直说没有资料,后端日志里 payload 长度只有 200 字。

中间走过弯路,把「用了三花括号但引入的版本不支持原始输出」当成主因,改完现象没变。

原因不止一个,得分开看。模板先过 markdown 渲染再过 mustache,双花括号被吞。少数情况下是mustache 默认转义 HTML,{{text}} 里的标签被清掉。

不容易想到的是,模板存在后端,前端拿到时已经被 sanitize 处理。

动手时先在 Node 里单独渲染同一份模板

node -e "const m=require('mustache');console.log(m.render('{{#c}}{{t}}{{/c}}',{c:[{t:'资料A'}]}))"

随后把渲染顺序改成先 mustache 后 markdown

node render.js --order mustache-first --template prompt.mustache --data ctx.json

然后对上下文变量使用原始输出块

node -e "const m=require('mustache');console.log(m.render('{{{ctx}}}',{ctx:'<p>资料A</p>'}))"

末了对比发送前后的 payload 长度

python -c "import json;print(len(json.load(open('payload.json'))['messages'][0]['content']))"

恢复的判定其实很直接。渲染后的 prompt 里上下文完整出现,payload 长度回到 1800 字左右,模型回答能引用资料里的具体条款。

提醒一点。双花括号同时是 mustache 语法和很多模板引擎的占位符,处理顺序错一步就会被静默吃掉;prompt 这类文本要禁用 markdown 渲染或改用不冲突的定界符。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189