工业智能体:从Codex/Claude到项目实战~系列文章12:Agentic RAG:让智能体“带着文献去决策“
第 12 期 | Agentic RAG:让智能体"带着文献去决策" 📚
摘要:高炉技术决策最怕"凭印象"。官方操作规程、历史事故案例、工艺论文,都是宝贵的先验知识。RAG(Retrieval-Augmented Generation,检索增强生成)便是把"外部知识"注入 LLM 的标准手段,而 Agentic RAG 则更进一层——让智能体按需、迭代地检索,把"固定查一次"升级为"像专家一样边查边想边复核"。本文从架构与工程双线展开:先对比经典 RAG 与 Agentic RAG 的差异,再构建一个"高炉事故处置"的 Agentic RAG 系统(LangChain 实现,含文档切分、向量检索、工具调用、多轮检索),最后给出**检索质量评估(Recall/Precision)**与落地建议,让"智能体带文献做决策"不再是口号。
〇、引言:知识不进模型,模型就是"裸奔"
大模型的知识有"截止日期"且不覆盖企业内部规程。把"你的知识库"接上智能体,它才能既不越权、又能给出有依据的处置。对钢厂来说,向量库里的"事故案例 + 操作手册"就是智能体决策的依据"。
一、经典 RAG vs Agentic RAG:一个"单程",一个"专家" 🧭
| 维度 | 经典 RAG | Agentic RAG |
|---|---|---|
| 检索触发 | 每次固定先检索 | 按需、多轮、可改 query |
| 上下文利用 | 单次拼接 | 与实时数据融合 |
| 适合场景 | 知识问答 | 诊断、处置、复核 |
💡 知识卡片:Agentic RAG 本质是"用 ReAct 循环包裹检索"——模型自己判断"要不要再查、查什么、引用哪条证据"。这对"事故处置要不要查历史案例"这种开放问题尤其有效。
二、构建"高炉事故处置" Agentic RAG(LangChain 实现)🛠️
uv add langchain langchain-openai langchain-community faiss-cpu
# rag/bf_rag.py —— 高炉事故处置 Agentic RAG
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.tools import tool
# 1) 把操作手册切块并向量化(入库一次)
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=80)
docs = splitter.split_documents(load_sop_pdf("docs/bf_sop.pdf"))
store = FAISS.from_documents(docs, OpenAIEmbeddings())
@tool
def search_sop(query: str) -> str:
"""按需检索操作手册/事故案例,返回最相关的3段原文。"""
hits = store.similarity_search(query, k=3)
return "\n---\n".join(d.page_content for d in hits)
@tool
def query_realtime(payload: str) -> str:
"""查询当前/最近炉况实时数值。"""
# 由第13/14期 OT-IT 与时序工具提供
return get_recent_tags(payload)
# 2) 智能体:融合 规程检索 + 实时数据 做处置
def decide():
llm = ChatOpenAI(model="claude-3-7-sonnet-20250219")
# 用 ReAct 让模型自行决定:查哪个规程、是否需要实时数据、如何给建议
return react_llm_with_tools(llm, tools=[search_sop, query_realtime],
question="热风压力0.46MPa且炉温下探,如何处理?")
📌 实战要点:切块大小直接决定检索质量。工业术语密集,建议
chunk_size=400~600并保留上下文重叠(overlap 10-20%),避免把"诊断"与"处置"硬切散。
三、别让检索结果"跑偏":质量评估 Recall/Precision 📐
任何 RAG 上线前都要量化"检索得对不对",否则只能靠感觉。这里给一个轻量评估脚本:
# rag/evaluate.py —— 检索质量评估
def evaluate(top_k_hits, gold_doc_ids):
"""给定检索结果与标注的相关文档,计算 Recall 与 Precision@k"""
rel = set(gold_doc_ids)
if not rel:
return {"recall": 0.0, "precision": 0.0}
hit = rel.intersection(top_k_hits)
recall = len(hit) / len(rel)
precision = len(hit) / len(top_k_hits)
return {"recall": round(recall,3), "precision@k": round(precision,3)}
🎯 要点:建议用 20~50 条"标注过的真实查询"做回归基线。每次改动切分策略、embedding 模型或 top-k,跑一遍评估,分数不降再上生产。把 RAG 调优从"玄学"变成"工程"。
四、落地建议与避坑 🧯
| 坑 | 后果 | 对策 |
|---|---|---|
| 切块过小 | 上下文撕裂 | 合理 chunk+overlap |
| 知识过时 | 给错误依据 | 建立文档版本+过期提醒 |
| 幻觉引用 | 编造"规程" | 强制返回原文片段+来源编号 |
| 权限缺失 | 泄密 | 按角色过滤检索集合 |
⚠️ 提醒:RAG 的"权威性"取决于知识库本身的质量与时效。原始资料版本化、检索结果带来源是钢铁这种"责任重大"行业的最低底线——宁可"回答保守",不可"引用造假"。
〇、附录:RAG 管线质量评估的"三大不漏" 🔍
Agentic RAG 好不好,最终要看"该检索的有没有被检索到、可信的依据有没有被引用"。本附录补一套RAG 质量评估指标与示意代码,避免"答得流畅但依据错漏"。
# rag/eval.py —— RAG 检索质量评估(骨架)
def hit_rate(gold_docs, retrieved):
"""gold_docs: 参考答案应命中的文档; retrieved: 实际检索命中"""
return len(set(gold_docs) & set(retrieved)) / max(1, len(gold_docs))
def faithfulness(cited, answer_text):
# 简化: 检查回答引用的片段是否真实出现在检索文档中
return sum(1 for c in cited if c in answer_text) / max(1, len(cited))
| 指标 | 含义 | 关注 |
|---|---|---|
| 召回率 | 关键文献有没有找齐 | 别漏 |
| 命中率 | 检索与黄金答案的重合 | 找得准 |
| 忠实度 | 回答是否引用真实文档 | 别编 |
📌 实战要点:Agentic RAG 的"信任"取决于"依据可靠"——宁可让智能体说"信息不足、建议查证",也不要"自信地引用一个不存在的文献"。把"忠实度"当作上线硬指标(呼应第 26 期可靠)。
⚠️ 提醒:“答得顺"不等于"答得对”——LLM 可能用检索结果拼出流畅但错误的回答。评估一定要同时看"检索对不对"和"引用真不真",两手都要硬。
🎯 本期小结
- 经典 RAG 单程、Agentic RAG 按需迭代,后者更适合"诊断/处置/复核";
- 用 LangChain + FAISS 几十行即可搭出"规程检索 + 实时数据"的处置智能体;
- 切块大小 + overlap 直接影响检索质量,工业术语要保守切分;
- Recall/Precision 评估把 RAG 调优从玄学变工程;
- 权威性底线:知识版本化 + 结果带来源 + 权限按角色过滤。
🔧 本期工具箱
- 依赖:
uv add langchain langchain-openai langchain-community faiss-cpu; - 评估:
evaluate.py(Recall/Precision); - 延伸阅读:第 04 期(技术栈 RAG 小节)、第 09 期(MCP 给 RAG 接实时数据)。
下一期预告:知识能"带文献决策"了,可数据还卡在"最后一公里"。第 13 期《高炉数据接入:从 PLC/DCS 到智能体的 OT-IT 打通》,把工业数据的"梗阻"一次打通。
作者:高炉炼铁智能化技术研究者,专注钢铁冶金与人工智能 + 交叉领域。
👍 如果觉得有帮助,请点赞、收藏、转发!
版权归作者所有,未经许可请勿抄袭,套用,商用(或其它具有利益性行为)。
🔔 关注专栏,不错过后续精彩内容
更多推荐



所有评论(0)