
最近系统学习了应用AI工程,踩了不少坑,这篇把核心问题说清楚。
之前以为Prompt就是往ChatGPT里敲个问题,测一次就完事。实际做项目才发现,这套在生产环境撑不过三天。下面是从第一章整理的笔记和图表,关于怎么让LLM(大语言模型)输出稳定可靠,最后还有一个我设计的实时核查系统。
计算器是确定性的(2 + 2 永远等于 4)。LLM是随机性的,它通过掷骰子按照概率预测下一个词。我们用Temperature(温度参数)来控制这个骰子:
Prompt: "The dog chased the..." ├─ "ball" (50%) ◄── Temp = 0 (Always picks #1 top choice. Good for facts) ├─ "cat" (30%) └─ "car" (10%) ◄── Temp = 1 (Rolls the dice. Good for creative poems)
关键点: 设置 Temperature = 0 并不能阻止幻觉。模型不会在 0 处停止预测。如果它不知道答案,概率最高的猜测仍然是一个编造的事实,而且它会每次都返回那个错误答案。
对于LLM来说,在屏幕上生成token就是它的思考过程。如果你问一个刁钻的谜题,却强迫它立刻给出一个词的答案,它没有时间计算,直接猜错。
用户不想看到满屏的机器人思考过程。要隐藏思考过程,在JSON Schema里定义一个 "thinking" 变量(后端隐藏)和一个 "answer" 变量(前端渲染)。
❌ WRONG ORDER ✅ RIGHT ORDER
{ { "answer": "Weak!", "thinking": "Step 1: 14 chars...", "thinking": "Wait, 14 chars..." "answer": "Strong!"
} }
(AI guesses before thinking, (AI thinks first, then locks in and cannot backspace to fix it) the right answer)
真实用户使用你的应用时,Prompt会以可预测的方式失效。下面是LLM注意力机制的工作原理及防御方法:
Attention High │ ★ System Rules (Put core rules at the start) │ Low │ ░░░ 10 Pages of Policy / Data (Lost in the Middle) ░░░ │ <userMessage>{Untrusted Input}</userMessage>
High │ ★ Sandwich Reminder (Put final rule here to beat Recency Bias) └────────────────────────────────────────────────────────► Prompt
<userMessage> 标签包裹输入,并在最底部添加规则提醒。在Prompt里说 "请只返回JSON" 只是一厢情愿。AI迟早会加上 "好的!这是你的JSON:" 然后让你的应用崩溃。
结构化输出(约束解码)通过将无效token的概率设为0%来物理阻断它们:
AI wants to reply: "Sure!" (70%) ──► Blocked (0%) ❌ "Here" (20%) ──► Blocked (0%) ❌ "{" (10%) ──► Allowed (100%) ✅
我用的两条Schema规则:
"s": string,用 "sentiment": "positive" | "negative" | "neutral"。| null 退路: 符合JSON语法不代表是事实。如果 "github_url": string 是必填字段,但简历里没有链接,AI就会被迫编一个假URL来满足Schema。用 string | null 让它安全地输出 null。不要只测一次Prompt("感觉没问题"),也别写一个巨型Prompt。可靠的系统使用评估集(20到50个保存的测试用例来捕捉回归)和带重试 guardrails 的Prompt链:
[Step 1: Translate] ──► [Step 2: Check Rule] ──► [Guardrail (if/else)]
(Fast/Cheap Model) (Smart Model) │ ▲ ├─ Pass ──► [UI Output] └─── Retry + Error Msg ─────┘ (Fail)
拆解步骤后,哪一步出问题一目了然,只需要调整那一步。
为了把上面的内容串起来,我用Excalidraw设计了一个Agent工作流,做了一个叫TruthPulse的事实核查应用。
点击查看我从V1到V2修复的3个bug
url 字符串给 Web_search_tool。由于LLM不知道当下的URL,它们会编出死链。V2里我改成了传 query: string(搜索关键词)。"error": string,这会逼着AI在核查成功时也编一个错误。V2里改成了 "error": string | null。{"retry": "true" | "false"} 检查,加上 max_retries = 3 上限,防止搜不到的谣言死循环。
┌───────────┐ │ Input │ └─────┬─────┘ ▼ <userMessage>{value}</userMessage>
Remember: Only claim the given fact │ ▼ ┌───────────────────────────────────────────┐ │ Main Agent + Thinking (Temp = 0) │◄────────────┐ │ "Strict fact checker... if invalid return │ │ │ error, else pass query: string to tool" │ │ └──────────┬───────────────────────┬────────┘ │ │ │ │ query: string │ │ (Invalid input) │ ▼ │ │ ┌─────────────────────┐ │ │ │ Web_search_tool │ │ │ └──────────┬──────────┘ │ Retry = true │ │ string │ (max_retries=3) │ ▼ │ │ ┌─────────────────────┐ │ │ │ Judge Prompt │ │ │ │ Compare source with │ │ │ │ userMessage │ │ │ └──────────┬──────────┘ │ │ ▼ │ │ ┌─────────────────────┐ │ │ │ {"retry": "true" | ├────────────┼──────────────────────┘ │ "false"} │ │ └──────────┬──────────┘ │ │ false │ ▼ ▼ ┌───────────────────────────────────────────┐ │ { │ │ "thinking": string, │ │ "claim": "true"|"false"|"unverified", │ │ "error": string | null │ │ } │ └───────────────────────────────────────────┘
第一章最大的收获:AI工程不是找到一个魔法Prompt就完事了。因为LLM是概率性的,真正的功夫在于围绕模型搭建标签、Schema、链式调用和重试guardrails,让应用在AI偶尔翻车时依然稳定可靠。