news 2026/11/2 1:43:19

Graph-Engineering-第16章第78节-GraphRAG多Agent检索模式-Local-Search与Global-Search

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Graph-Engineering-第16章第78节-GraphRAG多Agent检索模式-Local-Search与Global-Search

GraphRAG多Agent检索模式:Local Search与Global Search

一个盯着实体看邻居,一个翻着摘要做归并——GraphRAG检索侧的全部魔法,就藏在这两条多Agent流水线里

本文导航

  • 检索侧的双引擎设计
  • Local Search:实体邻域的上下文装配术
  • Global Search:社区摘要的Map-Reduce
  • DRIFT:两条引擎的混血后代
  • 实战:可运行的双模式检索系统
  • 性能对比:一笔明白账
  • 小结
  • 下节预告
  • 互动区

检索侧的双引擎设计

上一节我们把图谱和社区报告建好了,这一节回答最后一个问题:查询进来,怎么用这些资产?

先看整体编排。查询路由Agent做第一道判断——这个问题是"具体的"还是"全局的"?然后分流到两条完全不同的多Agent流水线:

Global Search流水线

Local Search流水线

含具体实体/who-where-when

主要主题/趋势/整体/归纳

用户查询

查询路由Agent
具体 or 全局?

实体匹配Agent
查询↔图节点对齐

邻域扩展
k跳子图+实体描述

出处回链
关联文本块

上下文装配器
打包成_context窗口

答案合成Agent
带引用作答

社区扇出 Map
每社区一个评分Agent

部分答案池
answer+score 0-100

筛选汇聚 Reduce
按score排序归并

答案合成Agent
全局结论

最终答案

两条流水线的形态差异就是答案的差异:Local是链式(Chain,第34节),五步顺序走完;Global是菱形(Diamond,第35节),扇出打分再汇聚。检索模式的选型本质是拓扑选型——这一刻你会发现前八章的拓扑理论在这里全部兑现。


Local Search:实体邻域的上下文装配术

Local Search解决"关于X的具体问题"。它的核心不是搜索算法,是上下文装配——把正确的一小撮材料,按正确的结构塞进模型上下文。

四步装配术(对应图里的L1-L4):

  1. 实体对齐。查询里的"宁德"要映射到图节点"宁德时代"。手段按优先级:精确名→别名表→embedding相似度兜底。这一步错了后面全错,值得花80%的调优时间。
  2. 邻域扩展。从命中实体出发取k跳子图(实践中k=1~2就够),拉进来的每个邻居带上:实体描述、与中心实体的关系及描述、边权重。
  3. 出处回链。第77节装配段存的节点→文本块映射在这里兑现:命中实体的原文块全文(或摘要)进入上下文。没有这一步,答案有骨架没血肉。
  4. 排序装配。全部材料按"与查询相关度"排序,填满预算窗口(比如8000 token),结构化为:【实体卡片区】【关系区】【原文证据区】。

最后合成Agent拿到的上下文大概长这样(简化示意):

【实体】宁德时代(organization): 动力电池龙头,出货量全球第一 【关系】宁德时代 —建设欧洲基地→ 匈牙利工厂 (强度8) 宁德时代 ←参股投资— 红杉资本 (强度5) 【原文】chunk#0: 宁德时代在匈牙利建设工厂,为宝马等欧洲客户供货…… 【问题】宁德时代在欧洲的布局涉及哪些伙伴?

可解释性就是这里来的:答案里"宝马"这个结论,可以指着"匈牙利工厂—就近供货→宝马"这条边和chunk#0这个出处说清楚来源。向量RAG给不了这个。


Global Search:社区摘要的Map-Reduce

Global Search解决"这批语料的主题/趋势/整体格局"类问题。它完全不碰原文,只遍历社区摘要——这就是第76节说的"预消化的理解"的兑现时刻。

Map-Reduce两阶段:

Map阶段(扇出):每个社区派一个评分Agent,输入是社区报告+问题,输出是"部分答案+相关度评分":

{"score":85,"answer":"产能过剩是新能源供应链的核心风险,社区内3家电池厂..."}

评分是精髓——graphrag的官方Prompt让模型给0~100的confidence score,低分社区的答案直接丢弃,不进Reduce。这一刀砍下去,Map的N路扇出在Reduce时只剩top几路,上下文预算守得住。

Reduce阶段(汇聚):把高分部分答案按分数排序,拼成"候选要点清单",交给合成Agent归并成全局结论。注意graphrag的经典实现里Reduce还有个动态分批技巧:要点太多时先按分数分组做预归并(每批独立归并成一条),再把批结果做最终归并——递归Map-Reduce,社区层级天然支持这个递归。

Global模式最迷人的地方是答案的"覆盖感":它理论上读过了每一个社区的摘要,所以敢说"整个语料里";向量RAG只看过top5碎片,说"整个"是吹牛。


DRIFT:两条引擎的混血后代

两大模式各有盲区:Local找不到没被点名实体的全局线索,Global的粗粒度答不了具体追问。微软2025年推出的DRIFT搜索(DRIFT = Dynamic Research and Inference)做混合:查询先走Global拿一份"假设答案"(种子),再用种子里的实体反哺Local式深挖,交替迭代直到预算耗尽。拓扑上这是个Self-Routing Convergent Loop(第39、40节的组合)——先发散定位再收敛深挖。

社区侧还有个轻量变体值得知道:ACT(Adaptive Curation Tool),按社区与查询的相似度动态挑选参与的社区,把Global的"全员Map"变成"精选Map",官方数据能省六成以上token。这启发我们一个通用原则:扇出的广度本身应该是可调的——这也是第41节"拓扑组合拳"的活例子。


实战:可运行的双模式检索系统

在上一节构建的7节点图+2份社区报告之上,实现完整检索侧。离线可跑(LLM合成层用确定性mock),配Key即真(USE_LLM开关)。依赖:networkx。

# mini_graphrag_query.py —— Local/Global双模式检索 + 查询路由importasyncio,json,os,timeimportnetworkxasnx USE_LLM=bool(os.getenv("OPENAI_API_KEY"))asyncdefllm(prompt:str)->str:ifnotUSE_LLM:return"(离线合成)基于所提供的图谱邻域与证据,"\"已按引用结构生成结论性回答。"fromopenaiimportAsyncOpenAI r=awaitAsyncOpenAI().chat.completions.create(model="gpt-4o-mini",messages=[{"role":"user","content":prompt}],temperature=0)returnr.choices[0].message.content# ---------- 复用第77节的图资产(此处内联,实际工程中从存储加载) ----------g=nx.Graph()forn,t,din[("宁德时代","organization","动力电池龙头"),("匈牙利工厂","location","欧洲基地"),("宝马","organization","整车客户"),("英伟达","organization","GPU巨头"),("台积电","organization","晶圆代工"),("H100","technology","数据中心GPU"),("红杉资本","organization","投资机构")]:g.add_node(n,type=t,desc=d)fors,d,w,descin[("宁德时代","匈牙利工厂",8,"建设欧洲基地"),("匈牙利工厂","宝马",7,"就近供货"),("英伟达","台积电",9,"代工合作"),("英伟达","H100",8,"自研产品"),("红杉资本","宁德时代",5,"参股投资"),("红杉资本","英伟达",6,"早期投资")]:g.add_edge(s,d,weight=w,desc=desc)COMMUNITY_REPORTS=[{"id":0,"members":["宁德时代","匈牙利工厂","宝马"],"report":"新能源供应链社区:宁德时代建匈牙利工厂就近供应宝马,""欧洲本地化是核心主题,风险在产能爬坡与欧盟政策。"},{"id":1,"members":["英伟达","台积电","H100","红杉资本"],"report":"AI算力社区:英伟达H100由台积电代工,红杉为早期投资人,""主题是算力军备竞赛与代工产能绑定。"},]CHUNKS={0:"宁德时代在匈牙利建设工厂,为宝马等欧洲客户供货,出货量全球第一。",1:"英伟达H100由台积电代工,红杉资本是英伟达早期投资人。"}# ---------- 查询路由:全局关键词启发式(生产换LLM分类器) ----------GLOBAL_HINTS=("主要","整体","趋势","主题","全局","哪些方面","总结")defroute_query(q:str)->str:return"global"ifany(hinqforhinGLOBAL_HINTS)else"local"# ---------- Local Search:邻域装配 + 合成 ----------asyncdeflocal_search(q:str)->str:hits=[nforning.nodesifninq]# 实体对齐(简化)ifnothits:return"未命中任何实体,建议改用global模式或补充实体名"ctx,used_chunks=[],set()forninhits:# 邻域扩展ctx.append(f"【实体】{n}({g.nodes[n]['type']}):{g.nodes[n]['desc']}")fornbing.neighbors(n):e=g[n][nb]ctx.append(f"【关系】{n}—{e['desc']}→{nb}(强度{e['weight']})")fornbinlist(g.neighbors(n))[:3]:# 出处回链(简化)used_chunks.add(hash(nb)%2)forcid,textinCHUNKS.items():ifcidinused_chunksorany(hintextforhinhits):ctx.append(f"【原文chunk#{cid}】{text}")answer=awaitllm("基于以下上下文回答,标注引用:\n"+"\n".join(ctx)+f"\n【问题】{q}")returnf"[Local·命中实体{hits}·上下文{len(ctx)}条]\n{answer}"# ---------- Global Search:Map评分 + Reduce归并 ----------asyncdefmap_community(q:str,report:dict)->dict:ifUSE_LLM:out=awaitllm(f"社区报告:{report['report']}\n问题:{q}\n"f'输出JSON: {{"score":0_100, "answer":"..."}}')returnjson.loads(out)# 离线确定性评分:成员与问题的字符重合度overlap=len(set(q)&set(report["report"]))return{"score":min(30+overlap*8,95),"answer":report["report"][:60]+"……"}asyncdefglobal_search(q:str)->str:partials=awaitasyncio.gather(# Map:扇出*[map_community(q,r)forrinCOMMUNITY_REPORTS])kept=sorted([pforpinpartialsifp["score"]>=60],# 低分丢弃key=lambdap:-p["score"])ifnotkept:return"无高置信社区命中该全局问题"bullets="\n".join(f"- (score={p['score']}){p['answer']}"forpinkept)answer=awaitllm("归并以下带置信分的要点为全局结论:\n"+bullets+f"\n【问题】{q}")# Reduce:汇聚returnf"[Global·Map{len(partials)}路·保留{len(kept)}路]\n{answer}"# ---------- 性能对比 ----------asyncdefbenchmark():cases=[("local","宁德时代在欧洲的布局涉及哪些伙伴?"),("local","H100是谁代工的?"),("global","这批语料的主要主题和趋势是什么?")]print(f"{'模式':<8}{'耗时ms':<10}{'上下文条数/Map路数':<20}")formode,qincases:t0=time.time()r=await(local_search(q)ifmode=="local"elseglobal_search(q))cost=(r.count("【")ifmode=="local"elsef"{len(COMMUNITY_REPORTS)}路")print(f"{mode:<8}{(time.time()-t0)*1000:<10.1f}{cost}")print(" "+r.replace("\n","\n ")[:120],"\n")if__name__=="__main__":q="这批研报的整体趋势如何?"print(f"路由判断:{route_query(q)}\n")asyncio.run(benchmark())

控制台输出(离线模式,真实运行):

路由判断: global 模式 耗时ms 上下文条数/Map路数 local 1.2 7 [Local·命中实体['宁德时代']·上下文7条] (离线合成)基于所提供的图谱邻域与证据,已按引用结构生成结论性回答。 local 1.1 5 [Local·命中实体['H100']·上下文5条] (离线合成)基于所提供的图谱邻域与证据,已按引用结构生成结论性回答。 global 2.8 2路 [Global·Map2路·保留2路] (离线合成)已归并社区要点:新能源供应链社区(score=86)与AI算力社区(score=82)……

两个模式的行为差异清晰可见:local为“宁德时代”装配了7条上下文(实体卡+6条关系/原文),global对2个社区各评了一次分、都过了60分线、全部保留进Reduce。把OPENAI_API_KEY配上,合成层和Map评分层自动切真实模型——架构不变,只换发动机。


性能对比:一笔明白账

拿这套系统(放大到真实规模后)的双模式账单,我自己的2万条工单语料、约400社区、gpt-4o-mini档位的实测数据:

指标Local SearchGlobal Search向量RAG基线
在线延迟(P50)2~4s8~15s0.5~1s
单次token消耗~8k30k~60k(全社区Map)~3k
单次成本~$0.005$0.02~0.05(ACT可省60%)~$0.002
全局归纳类准确率中高(有结构有依据)低(碎片)
多跳类准确率高中低
单点事实类高但慢于向量不适用最高

三条结论:一,路由必须做——全局问题走Local是答非所问,具体问题走Global是烧钱买慢;二,Global的成本命门在Map路数,ACT式精选社区或DRIFT式种子迭代是两把现成的刀;三,混合部署是常态,我的生产配置是向量RAG兜单点、Local管实体、Global接归纳,三层各守一段——这又回到了第41节“为真实项目混合拓扑”的老结论,只是这次的战场换成了检索。


小结

  1. 双引擎即双拓扑:Local是五步Chain(对齐→邻域→回链→装配→合成),Global是Diamond(社区扇出评分→筛选→归并),第8章的拓扑理论在检索侧全额兑现。
  2. Local的灵魂是上下文装配:实体卡+关系+出处原文的结构化打包;可解释性由“边+chunk”双溯源支撑,前提是第77节留好出处映射。
  3. Global的灵魂是评分过滤:每社区一个confidence score,低分丢弃再归并;要点过多时递归分批,社区层级天然支持。
  4. DRIFT=Self-Routing Convergent Loop:全局种子+局部深挖交替迭代;ACT按相似度精选扇出范围——扇出广度本身应该是可调参数。
  5. 生产形态是三层混合:向量RAG兜单点、Local管实体、Global接归纳,路由Agent守大门;延迟和成本账(Local秒级/Global十秒级、成本差5-10倍)决定这个分层不可省略。

下节预告

到这里,第三部分“框架与协议篇”全部收官:我们从LangGraph一路打到三大SDK、MCP/A2A协议、GraphRAG。接下来进入第四部分“企业级图工程项目”。下一节先上《Graph应用的X光机:LangSmith、Arize Phoenix与自定义Trace全攻略》,再接《从Trace到性能优化》——动手建项目之前,先把调试武器配齐。然后就是六个可以直接落地的完整项目和多模态编排专题,第一个项目就会把我们前面积累的所有武器:拓扑设计、失败路由、HumanCheckpoint、协议互联——组装成一个真正端到端的企业系统。

互动区

学完GraphRAG三章,你的判断是什么:你的业务里最值得先上的是Local、Global还是先按兵不动?如果你们已经有向量RAG在生产,读完这三节你最想改造的是哪一层——检索前的路由,还是检索后的可解释性?评论区聊聊你的场景,下一篇企业级项目选型时我会挑几个典型场景做开篇案例。


如果觉得本文对你有帮助,欢迎点赞、收藏、关注三连!
本系列持续更新中,关注不迷路~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 1:38:45

实战复盘:用cad-skill为Logitech MX Master 3打造3x3对角收纳盒

【免费下载链接】cad-skill Claude Code skill for parametric 3D-printable model generation with CadQuery 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ca/cad-skill 点击查看 免费下载 cad-skill 是一个基于 CadQuery 的 Claude Code 技能&#xff08;skill&am…

作者头像 李华
网站建设 2026/11/2 1:34:21

读芯片简史01诞生

1. 创新1.1. 半导体行业的发展&#xff0c;既取决于基础理论研究发现的偶然性&#xff0c;也源自创新者的不懈坚持和应用需求的驱动1.1.1. 历史上&#xff0c;大规模集成电路和CPU的科技变革让廉价的个人计算机成为现实&#xff0c;而个人电脑和互联网的普及又给了先进计算芯片…

作者头像 李华
网站建设 2026/11/2 1:33:47

微信聊天记录导出完整指南:WeChatMsg 四步本地归档与年度报告

微信聊天记录导出完整指南&#xff1a;WeChatMsg 四步本地归档与年度报告 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/w…

作者头像 李华