Agent检索与输出精确性提升

发布时间:2026/9/28 3:41:34

Agent检索与输出精确性提升
提高 Agent 的检索精度和输出精度核心思想只有一句话把线性 RAG改成带评估与纠错的图。单趟检索→塞给 LLM→输出必然会出现三种典型失败查询词和文档语义错位、Top-K 里混入高分低相关内容、生成时出现无依据的幻觉论断。LangGraph 的价值就是让你用节点 条件边把评估、改写、重试、人工兜底编程进流程 。一、检索精确性从相似度走向相关性传统 RAG 默认向量相似 ≈ 相关但在生产环境中这经常不成立——一篇关于 Apache 的 TLS 文章可能因为语义接近而排在 Nginx HTTPS 配置答案前面 。要从根本上提升检索精度需要在索引端和检索端同时做工。1. 索引端让被检索的块本身就是高质量的 结构感知切分Structure-Aware Chunking不要用固定的CharacterTextSplitter一刀切。Markdown / HTML 文档应当先按标题层级切再做二次递归切分这样每个 chunk 都带有section_path之类的元数据检索时能定位到具体章节 。fromlangchain_text_splittersimportMarkdownHeaderTextSplitter,RecursiveCharacterTextSplitter header_splitterMarkdownHeaderTextSplitter(headers_to_split_on[(#,h1),(##,h2),(###,h3)])sub_splitterRecursiveCharacterTextSplitter(chunk_size800,chunk_overlap100)defchunk_documents(raw_docs):all_chunks[]fordocinraw_docs:md_chunksheader_splitter.split_text(doc)forchunkinmd_chunks:iflen(chunk.page_content)800:sub_chunkssub_splitter.split_documents([chunk])all_chunks.extend(sub_chunks)else:all_chunks.append(chunk)returnall_chunks参数经验值来自生产实践中文通用文档chunk_size500, overlap100技术文档/论文chunk_size800, overlap150法律条款chunk_size800, overlap200按第X条切代码chunk_size200, overlap30overlap 的作用至关重要——一段话如果被切到中间前后两块都不完整检索时两块都匹配不上 。 父子文档切分Parent Document Retriever用小 chunk 做精确嵌入匹配但返回给 LLM 时用大 chunk 保留上下文 fromlangchain.retrieversimportParentDocumentRetrieverfromlangchain.storageimportInMemoryStore child_splitterRecursiveCharacterTextSplitter(chunk_size200)# 用于嵌入parent_splitterRecursiveCharacterTextSplitter(chunk_size2000)# 用于返回retrieverParentDocumentRetriever(vectorstorevectorstore,docstoreInMemoryStore(),child_splitterchild_splitter,parent_splitterparent_splitter,) 元数据注入每个 chunk 必须带doc_source、time_updated、section_path。这些是后续做元数据过滤如filter{region: EMEA, department: IT}的基础 。2. 检索端混合检索 查询改写 重排序 混合检索Dense Sparse纯向量检索在术语精确匹配上会翻车如ESG碳排放等专业词。BM25 弥补了这一点fromlangchain.retrieversimportBM25Retriever,EnsembleRetriever bm25_retrieverBM25Retriever.from_documents(docs)vector_retrievervectorstore.as_retriever()ensemble_retrieverEnsembleRetriever(retrievers[bm25_retriever,vector_retriever],weights[0.3,0.7]# 语义匹配权重更高)✍️ 查询改写Query Rewriting用户的原始 query 经常含糊“手机点了坏链接怎么办”需要先改写成检索友好形式“移动设备钓鱼邮件事件响应流程”fromlangchain.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportStrOutputParser rewrite_promptChatPromptTemplate.from_messages([(system,你是一个查询改写器。给定用户问题将其改写为更适合向量数据库检索的形式使其更具体或使用不同的关键词。仅返回改写后的问题。),(human,原始问题{question}),])rewrite_chainrewrite_prompt|llm|StrOutputParser()defrewrite_query(state):rewrittenrewrite_chain.invoke({question:state[question]})return{question:rewritten,rewrite_count:state.get(rewrite_count,0)1} 重排序RerankingBi-encoder嵌入模型召回快但不精确Cross-encoder 重排能把 Query-Document 对联合打分精度显著提升 fromlangchain.retrievers.contextual_compressionimportContextualCompressionRetrieverfromlangchain_community.cross_encodersimportHuggingFaceCrossEncoderfromlangchain.retrievers.document_compressorsimportCrossEncoderReranker# 先用向量库宽召回 k20base_retrievervectorstore.as_retriever(search_kwargs{k:20})# 再用 Cross-encoder 重排取 top 5cross_encoderHuggingFaceCrossEncoder(model_nameBAAI/bge-reranker-base)rerankerCrossEncoderReranker(modelcross_encoder,top_n5)retrieverContextualCompressionRetriever(base_compressorreranker,base_retrieverbase_retriever,) 进阶HyDE假设文档嵌入让用户 query 先生成一段假设性答案再用这段答案去检索能显著提升语义对齐 defhyde_retrieve(state,retriever,model):hyde_promptf请写一段可能回答以下问题的文档内容{state[query]}hypothetical_docmodel.invoke(hypothetical_doc).content docsretriever.invoke(hypothetical_doc)return{retrieved_docs:docs}二、输出精确性让 Agent 学会自我纠错光有好的检索还不够。要让最终输出精确必须在图中加入评估节点和条件重试。这是 LangGraph 相比 Chain 最大的优势——决策可编程。1. 文档相关性评分GraderLLM 对每条检索到的文档打分相关/不相关过滤掉高分低相关的噪声 frompydanticimportBaseModel,FieldclassGradeDocument(BaseModel):对检索文档的相关性评分score:strField(descriptionyes 表示相关no 表示不相关)grade_promptChatPromptTemplate.from_messages([(system,你是文档相关性评估器。判断检索到的文档是否包含能回答用户问题的关键信息。),(human,文档{document}\n\n问题{question}),])doc_gradergrade_prompt|llm.with_structured_output(GradeDocument)defgrade_documents(state):questionstate[question]documentsstate[documents]filtered[]fordocindocuments:resultdoc_grader.invoke({document:doc.page_content,question:question})ifresult.scoreyes:filtered.append(doc)return{documents:filtered}2. 幻觉检测Hallucination Check生成答案后验证答案中的每一个论断是否都能在检索文档中找到支撑 classGradeHallucination(BaseModel):score:strField(descriptionyes 表示答案完全由检索文档支撑no 表示存在无依据的论断)hallucination_promptChatPromptTemplate.from_messages([(system,判断生成答案中的每个事实论断是否都能在检索文档中找到依据。),(human,文档{documents}\n\n答案{generation}),])hallucination_graderhallucination_prompt|llm.with_structured_output(GradeHallucination)defcheck_hallucination(state):resulthallucination_grader.invoke({documents:state[documents],generation:state[generation],})return{hallucination_check:result.score}3. 答案质量评估Answer QualityclassGradeAnswer(BaseModel):score:strField(descriptionyes 表示答案切实回应了问题no 表示答非所问)answer_graderanswer_prompt|llm.with_structured_output(GradeAnswer)defcheck_answer_quality(state):resultanswer_grader.invoke({question:state[question],generation:state[generation],})return{answer_quality:result.score}4. 强制引用与 citation 校验为防止 LLM 编造引用如CITATION: [fake_source]需要在 prompt 中强制要求输出格式为 后处理校验提取答案中的所有 citation 编号确认其确实存在于state[documents]列表中不存在的 citation 一律剔除并触发重新生成5. 重试预算Retry Budget—— 防止无限循环这是生产环境最容易踩的坑。如果不设上限一个知识库中根本没有答案的问题会让 Agent 无限改写-重试 defdecide_after_grading(state):ifstate[relevance_decision]relevant:returngenerateifstate.get(rewrite_count,0)2:# 最多改写 2 次returngenerate# 用现有文档硬生成returnrewrite三、LangGraph 完整实现自纠错 RAG Agent把上面所有环节组装成一个图。状态定义如下 fromtypingimportTypedDict,List,Annotatedfromlangchain_core.documentsimportDocumentimportoperatorclassGraphState(TypedDict):question:strdocuments:List[Document]generation:strrewrite_count:inthallucination_check:stranswer_quality:strerror_reason:str图的结构START → rewrite_query → retrieve → grade_documents │ ┌───────────────┼───────────────┐ relevant not relevant rewrite_count2 │ │ │ generate ───────► rewrite_query generate │ check_hallucination │ ┌───────┼───────┐ grounded not_grounded (回到 generate) │ check_answer_quality │ ┌─────┼─────┐ useful not_useful (回到 rewrite_query 或 finish) │ FINISH核心节点实现fromlanggraph.graphimportStateGraph,END workflowStateGraph(GraphState)# 1. 查询改写节点workflow.add_node(rewrite_query,rewrite_query)# 2. 检索节点混合检索 重排defretrieve(state):querystate[question]# 这里可以注入 metadata 过滤documentsensemble_retriever.invoke(query)return{documents:documents}workflow.add_node(retrieve,retrieve)# 3. 文档评分节点workflow.add_node(grade_documents,grade_documents)# 4. 生成节点defgenerate(state):promptChatPromptTemplate.from_template(你是一个企业知识库助手。仅基于提供的上下文回答问题。\n上下文\n{context}\n\n问题{question}\n\n要求\n1. 答案必须以 [citation:N] 标注来源\n2. 如果上下文无法回答问题明确说我不知道\n3. 禁止编造信息)chainprompt|llm context\n\n.join([doc.page_contentfordocinstate[documents]])generationchain.invoke({context:context,question:state[question]}).contentreturn{generation:generation}workflow.add_node(generate,generate)# 5. 幻觉检测节点workflow.add_node(check_hallucination,check_hallucination)# 6. 答案质量节点workflow.add_node(check_answer_quality,check_answer_quality)# 边和条件路由workflow.set_entry_point(rewrite_query)workflow.add_edge(rewrite_query,retrieve)workflow.add_edge(retrieve,grade_documents)defdecide_after_grading(state):ifnotstate[documents]:returnrewriteifstate.get(rewrite_count,0)2:returngeneratereturnrewriteworkflow.add_conditional_edges(grade_documents,decide_after_grading,{generate:generate,rewrite:rewrite_query})workflow.add_edge(generate,check_hallucination)defdecide_after_hallucination(state):returngenerateifstate[hallucination_check]not_groundedelsecheck_answer_qualityworkflow.add_conditional_edges(check_hallucination,decide_after_hallucination,{generate:generate,check_answer_quality:check_answer_quality})defdecide_after_quality(state):ifstate[answer_quality]not_useful:ifstate.get(rewrite_count,0)2:returnfinishreturnrewritereturnfinishworkflow.add_conditional_edges(check_answer_quality,decide_after_quality,{rewrite:rewrite_query,finish:END})appworkflow.compile()四、人在回路Human-in-the-Loop终极精确性兜底对于高风险场景如发邮件、删数据库、对外承诺可以让 Agent 在执行工具前暂停等待人工审批 fromlanggraph.typesimportinterrupt,Commandfromlanggraph.checkpoint.memoryimportMemorySaverdefreview_tool_call(state):在工具真正执行前暂停让人审批/编辑/拒绝tool_callstate[messages][-1].tool_calls[0]human_responseinterrupt({question:批准此操作,tool_name:tool_call[name],tool_args:tool_call[args],})ifhuman_response[type]approve:return{}elifhuman_response[type]edit:state[messages][-1].tool_calls[0][args]human_response[edited_args]return{messages:[state[messages][-1]]}else:# rejectreturn{messages:[ToolMessage(content用户拒绝了此操作。,tool_call_idtool_call[id])]}# 编译时必须带 checkpointer否则无法暂停/恢复memoryMemorySaver()graphworkflow.compile(checkpointermemory)五、性能优化从 2.3s 到 380ms 的真实路径检索精确性提升后延迟往往恶化。生产环境的几个关键优化 优化项操作效果向量库分片按source_type拆分 Chroma 为多子库-42% 耗时BM25 预热高频词结果预加载到内存 dict-28% 耗时异步并行检索asyncio.gather并行多通道timeout1.2s-31% 耗时Score 预计算归一化向量化时预计算为 [0,1] 存入 metadata-15% CPUimportasyncioasyncdefparallel_retrieve(query):tasks[vector_retriever.ainvoke(query),bm25_retriever.ainvoke(query)]resultsawaitasyncio.gather(*tasks,return_exceptionsTrue)# 合并 去重 重排...六、评估没有评估的优化都是瞎忙精确性提升必须可量化。建议跟踪以下指标检索侧RecallK、MRRMean Reciprocal Rank、重排后 Top-5 准确率生成侧Faithfulness忠实度、Answer Relevancy、Citation Accuracy端到端任务成功率、人工抽检合格率使用 LangSmith 或自定义日志追踪每一步的输入输出找出瓶颈节点 。最终总结提升 LangChain/LangGraph Agent 的精确性本质是把一次性管道重构成带评估回路的图。关键认知相似度 ≠ 相关性。向量检索只是宽召回的手段真正的精度来自评估-改写-重排-校验这一整套图节点协作。检索端要做的事结构感知切分 父子文档 元数据注入混合检索BM25 向量做宽召回Cross-encoder 重排序做精准排序查询改写消除查询鸿沟生成端要做的事文档相关性评分过滤噪声幻觉检测确保每句话有依据答案质量评估确保切题强制引用 citation 校验防编造重试预算防止无限循环架构端要做的事LangGraph 状态图把上述节点编程化人在回路兜底高风险操作性能优化保证生产可用性持续评估驱动迭代最常见的三个反模式❌ 不设重试上限 → 死循环烧钱❌ 只用向量检索不用重排 → Top-K 稀释❌ 编译时不加 checkpointer → 人在回路失效按这套思路落地检索精确性和输出精确性可以同时获得质的提升——其核心在于让 Agent 具备自我怀疑和自我纠错的能力而不是盲目相信第一趟检索和第一次生成。

相关新闻

ARM固件逆向:5种定位ELF入口点的方法与实战技巧

ARM固件逆向:5种定位ELF入口点的方法与实战技巧

2026/9/27 22:19:35

1. 项目概述:从固件二进制到可执行逻辑的逆向之旅在嵌入式安全、设备分析和漏洞挖掘的领域,我们常常会面对一个最基础也最关键的挑战:拿到一个设备的固件文件,如何找到它的第一行代码在哪里开始执行?这个问题&#xff…

智能监控告警系统2.0:动态基线算法与告警聚合实战

智能监控告警系统2.0:动态基线算法与告警聚合实战

2026/9/26 6:22:06

1. 项目背景与核心价值监控告警系统就像给IT基础设施装上的"神经系统",任何风吹草动都能第一时间感知。在运维领域干了十几年,我见过太多因为告警不及时导致的故障蔓延案例。传统的监控系统往往存在两个致命伤:要么误报满天飞让运维…

30米分辨率CATCD树木覆盖数据的技术解析与应用实践

30米分辨率CATCD树木覆盖数据的技术解析与应用实践

2026/8/23 1:29:45

1. 项目背景与数据价值作为一名长期从事地理空间数据分析的研究者,我深知高质量长时间序列地表覆盖数据的稀缺性。传统森林资源调查往往存在两个痛点:一是时间分辨率低(通常5-10年一次),二是空间细节不足(常…

CANN/GE ACL数据集缓冲区添加函数

CANN/GE ACL数据集缓冲区添加函数

2026/9/26 19:14:12

aclmdlAddDatasetBuffer 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Te…

用ffmpeg高效批量调整图片尺寸的实战指南

用ffmpeg高效批量调整图片尺寸的实战指南

2026/9/27 1:30:29

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

2026/9/28 2:15:29

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱 【免费下载链接】transformers 🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and mu…

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

2026/9/28 3:14:54

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system sup…

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

2026/9/27 1:30:34

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

2026/9/26 16:36:51

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting mi…

远程协作的工作台整理

远程协作的工作台整理

2026/9/26 14:29:04

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/26 13:57:22

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/26 23:35:16

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…