「从零到 AI 应用工程师」专栏 · 第 12 篇
前面三篇分别解决了:是什么、怎么切、怎么找。
今天把它们焊成一个接口:POST /rag/query------问一句设备运维问题,返回有依据的答案。
一、今天要做出什么
bash
curl -s -X POST http://127.0.0.1:8000/rag/query \
-H "Content-Type: application/json" \
-d '{
"question": "E001单体过压故障怎么处理",
"top_n": 5
}'
返回里至少有:
answer:回答正文references:送进模型的参考切片answer_source:llm/retrieval_fallback/refusal...
(下一篇再专讲 citations。)
二、在线链路逐步拆
text
question
→ 预处理(截断、脱敏)
→ Embedding(query)
→ 向量库 TopN
→ 相似度过滤(+ 可选 Rerank)
→ 拼 System / User Prompt
→ 大模型生成(或检索兜底)
→ 包装统一 JSON 返回
和 chat-api 的差别:多了检索上下文 ;Prompt 里必须写清------只能依据参考片段,禁止编造。
三、Prompt 怎么写才像「工业问答」
推荐 System + User 分离:
| 位置 | 内容 |
|---|---|
| System | 角色(运维助手)+ 硬约束(仅依据片段;无依据拒答;禁止「可能/大概」)+ 引用格式(【1】【2】) |
| User | <知识库参考片段> 编号列表 + 用户问题 |
大模型参数(运维场景偏保守):
| 参数 | 建议 | 原因 |
|---|---|---|
| temperature | 0.1 左右 | 少发散、少编流程 |
| max_tokens | 适中上限 | 防废话 |
| timeout | 明确超时 | 云端别无限挂起 |
LLM_ENABLED=false 时:可走检索摘录兜底(把 Top 片段拼成带编号的回答),方便无密钥时也跑通链路。
四、接口分层(复用阶段 1)
text
routers/rag.py # HTTP
→ services/... # 薄业务
→ rag/pipeline.py # 编排:检索→生成→后处理
→ store / embedding / llm
好处:换 FAISS↔pgvector、换模型厂商,上层路径可以不动。
五、过滤与截断别忘了
- 相似度阈值:太远的切片别进 Prompt(噪声会诱导幻觉)。
- 上下文总长上限:片段再多也截断,保护 token 账单与模型窗口。
- 空检索:不要硬调模型瞎聊------直接拒答或友好提示(详见第 14 篇)。
六、验收清单
- 手册内问题能答到点子上
-
references非空且人眼相关 - 明显超纲问题不瞎编(至少不一本正经输出假流程)
- 日志能看到检索 / 生成分段耗时(可选但强烈建议)
七、带走这三条
/rag/query= 检索 + 约束 Prompt + 生成。- 低温度 +「仅依据片段」是工业默认姿态。
- 编排放 pipeline,路由保持瘦------和 chat-api 同一套分层纪律。
下一篇:citations 引用溯源------让答案里的【1】【2】能点回 doc_id 与页码。
这是专栏第 12 篇。两到三天一更,出处见。