公司动态

03-M3-基础RAG-检索大模型让系统开口回答

📅 2026/8/22 16:23:13
03-M3-基础RAG-检索大模型让系统开口回答
检索 大模型让系统「开口回答」基础 RAG 落地实测M3系列城市管理 Agentic RAG —— 从零搭建城市管理问答系统本篇M3 · 基础 RAG实测版源码https://gitee.com/Chester_Xue/city-agentic-rag一、M2 之后还差什么M2 做完系统会「找」了问「暴雨」能捞回 3 段相关文本。但捞回来的是碎片不是人话气象局 预警等级.txt: 橙色3小时内降雨量将达50毫米以上... 应急局 防汛应急响应预案.txt: Ⅲ级暴雨红色预警或城区内涝积水点超过 20 处...市民要的是「暴雨橙色预警怎么响应」——一句完整、有条理、带出处的回答。这就是 M3检索增强生成RAG。上一版 M3 文章是设计稿当时代码还没写。现在代码落地了这篇是实测版三个文件、一个闭环、两条真实验收问答全部真实运行输出。二、RAG 在干什么大白话版把大模型想象成一个知识渊博但记性差的专家。你直接问他他可能凭印象瞎说这就是「幻觉」。RAG 的做法是先查资料把资料塞给他让他照着资料答。你的问题 │ ▼ [检索] 从 Chroma 捞出最相关的 3 段资料M2 已就绪 │ ▼ [拼接] 问题 资料 指令 Prompt │ ▼ [生成] 大模型照着资料回答标注引用来源关键点大模型只负责「组织语言」不负责「回忆知识」——知识来自检索到的真实资料从根上抑制幻觉。三、落地三个文件一个闭环1. retriever.py把「能查」包装成「好查」M2 的db.query()已经能查了M3 包一层更语义化的接口顺便把「来源标注」格式化好defretrieve(query:str,top_k:int3,dept_filter:str|NoneNone)-list[dict]:检索与 query 最相关的文本块。dbChromaVectorDB()returndb.query(query,top_ktop_k,dept_filterdept_filter)defformat_context(hits:list[dict])-str:把检索结果拼成 Prompt 上下文每段前标注来源。blocks[]fori,hitinenumerate(hits,1):metahit.get(metadata,{})deptmeta.get(dept,未知部门)fnamemeta.get(file,未知文件)blocks.append(f[{i}] (来源{dept}/{fname})\n{hit[content]})return\n\n.join(blocks)两个细节dept_filter参数是为 M4 的 Agentic 路由预留的通道——路由判断「这是气象问题」检索就只查气象省得拿民政的资料凑数。format_context给每段资料贴上「来源部门/文件名」的标签大模型回答时就能直接引用——这是让回答可溯源的关键一步。2. generator.pyLLMClient可替换的大模型客户端大模型接入做成一个类配置全部走.env项目 M0 就留好了位子classLLMClient:def__init__(self,api_type:strdeepseek):self.api_typeapi_type# 可扩展: openai / qwen / claudeself.api_keyos.getenv(API_KEY,).strip()self.base_urlos.getenv(API_BASE_URL,https://api.deepseek.com/v1)self.model_nameos.getenv(MODEL_NAME,deepseek-chat)ifnotself.api_key:raiseValueError(未配置 API_KEY请复制 .env.example 为 .env 并填入 API Key)defchat(self,prompt:str,temperature:float0.3,max_tokens:int1024)-str:调用大模型补全对话。fromopenaiimportOpenAI clientOpenAI(api_keyself.api_key,base_urlself.base_url)respclient.chat.completions.create(modelself.model_name,messages[{role:user,content:prompt}],temperaturetemperature,max_tokensmax_tokens,)returnresp.choices[0].message.content.strip()选型说明为什么 DeepSeek走 OpenAI 兼容协议openai库改个base_url就能用中文能力强、价格便宜原型阶段首选。为什么温度设 0.3问答场景要「稳」不要「飘」低温度减少发散。为什么构造时就校验 key.env没配好启动第一秒就报错而不是跑十轮问答才在中间炸掉。.env长这样API_KEY填你自己的gitignore 已忽略不会提交API_KEYsk-your-key-here API_BASE_URLhttps://api.deepseek.com/v1 MODEL_NAMEdeepseek-chat3. Prompt 模板RAG 的效果一半在 Prompt模板只有四行两条硬约束你是城市应急分析助手。根据以下从各部门检索到的资料回答问题。 必须标注引用来源部门文件名。信息不足请明确告知。 参考资料 {context} 问题{question}必须标注引用来源——回答自带出处可溯源、可核验用户能自己点开原文核对信息不足请明确告知——防止模型硬编造这是 M5「答案反思」的前置习惯4. cli.py把链路串起来python-msrc.cli 城市应急 Agentic RAG · 基础问答M3 输入问题开始问答输入 exit/退出 结束 ❓ 问题 输入 → 检索 → 拼 Prompt → 生成 → 打印含引用一个最简单的可用闭环。三条退出命令exit / quit / 退出随便用。四、真实验收两条问答全部带来源推进表 M3 的验收标准是两条跨部门问答我们逐个实测。验收 1问民政问题❓ 问题 XX街道独居老人有多少检索侧命中真实输出[0.7603] 民政局/弱势群体统计.txt [0.6438] 民政局/养老服务设施.txt [0.5048] 民政局/低保救助政策.txt前 3 条全来自民政局没有一条串到别的部门。生成侧回答节选 回答 XX街道独居老人为 156人来源民政局/弱势群体统计.txt。 若您需要其他街道或更近期的数据当前资料不足建议补充更新信息。 引用来源 - 民政局/弱势群体统计.txt - 民政局/养老服务设施.txt - 民政局/低保救助政策.txt✅返回民政数据 来源验收通过。验收 2问气象/应急问题❓ 问题 暴雨橙色预警怎么响应检索侧命中真实输出[0.7419] 气象局/预警等级.txt [0.7125] 应急局/防汛应急响应预案.txt [0.6494] 气象局/预警信号发布规范.txt生成侧回答节选 回答 根据现有资料暴雨橙色预警的响应要求如下 1. 响应启动条件气象部门发布暴雨橙色预警时启动Ⅳ级应急响应 2. 具体响应动作 - 各成员单位到岗值班 - 抢险队伍集结待命 - 避难场所开放 - 危险区域群众转移橙色及以上强制转移 3. 预警发布渠道市气象台官方微博、微信公众号、应急广播、短信平台 依据[1]气象局/预警等级.txt、[2]应急局/防汛应急响应预案.txt、 [3]气象局/预警信号发布规范.txt 信息不足说明资料未明确橙色预警对应的具体降雨量数值、强制转移的 具体人数范围需结合原始文件核对。 引用来源 - 气象局/预警等级.txt - 应急局/防汛应急响应预案.txt - 气象局/预警信号发布规范.txt✅返回气象数据 来源验收通过。注意回答末尾的「信息不足说明」——这是 Prompt 硬约束在起作用模型主动承认资料里没写清楚的东西而不是编一个数字糊弄你。「不编」比「答对」更难RAG 的价值就在这里。五、踩过的坑坑 1API Key 是拦路虎.env.example从 M0 就有但API_KEY一直是占位符。M3 开工第一件事就是填真 key——没有它生成环节整个跑不起来。教训M0 就把 key 申请好别拖到里程碑当天。坑 2模型偶尔「过度谨慎」验收 1 第一次跑模型开头先说「无法直接查询到 XX 街道独居老人的具体人数」绕了一大圈最后才给出 156 人。数据明明完全匹配它却先自我怀疑。这是大模型「过度对齐」的典型表现——prompt 里把「必须基于资料直接回答」写得再明确一点或者把检索分数0.76 已经很高作为置信度提示给它能缓解。这个问题 M5「答案反思」阶段会系统处理。坑 3别小看格式化的细节format_context里给每段加[1] (来源部门/文件名)前缀看起来只是排版实际是让模型回答时能指着编号说「依据[1]」——引用格式立刻规范了。Prompt 工程的胜负手往往在这些细节里。六、为 M4/M5 铺的路M3 是「地基」模块几个设计决策直接服务后面的 Agentic 阶段retriever的dept_filter参数 →M4 路由的落点路由说「这是气象问题」检索就只查气象Prompt 里「标注来源」的硬约束 →M5 反思时对照核查的依据回答和引用逐条比对编没编一目了然LLMClient(api_type...)可替换 → 换模型不改业务代码二期接国产大模型零成本七、下一步系统现在能「查」能「答」了但有个尴尬问「暴雨橙色预警怎么响应」它把气象、民政、热线的资料全捞出来一起答——检索是盲目的没有「意图」概念。下一步 M4Agentic 路由让系统先判断「这是个气象问题」再决定查哪个部门。下一篇M4 Agentic 路由让每个问题找到对的部门上一篇M2 切分与向量化让机器「看懂」城市知识系列目录城市管理 Agentic RAG —— 从零搭建城市管理问答系统想了解更专业的内容本文是项目实战记录。如果你对 RAG 的原理、Prompt 工程技巧、大模型 API 接入的完整方案感兴趣欢迎访问我的 CSDN 专栏喵本喵叁肆的 Agentic RAG 实战专栏阅读完整的技术博客系列含可运行代码、架构图与验收标准。