关于 hubmesh
hubmesh 是用于现有向量数据库之上的 Python GraphRAG 检索规划库,适合构建多跳检索的 RAG 系统。它以确定性图排序和预算感知的上下文打包规划检索,查询路径不调用大模型。
主要功能
- 01基于图的多跳检索规划
- 02融合余弦相关性与 PPR 排序
- 03按上下文预算打包结果
- 04支持 Qdrant、Chroma 与内存适配器
- 05实体解析与路径解释
适用场景
- 01检索需要跨实体关联的问题
- 02为现有向量数据库增加图检索
- 03逐跳检索并排除已用文档
MCP 相关
可选的 MCP 服务通过 stdio 或 SSE 暴露语料索引、检索、实体解析、图查询和文档读取等操作工具。查询工具不调用大模型,Agent 可自行规划多跳检索。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
hubmesh
感知中心性的 GraphRAG 检索规划器。可直接叠加在任意向量数据库之上。
hubmesh 是一个 Python 库,可基于现有向量数据库提升多跳 RAG 的质量。你无需替换现有基础设施,只需在向量数据库和大模型之间添加一个智能规划器。
这个工具解决的问题
简单的向量检索(“嵌入查询,按余弦相似度获取 top-k”)无法处理“收购 Slack 的那家公司的创始人出生在哪里?”这类多跳问题。要得出正确答案,需要沿推理路径检索实体,而不是只检索最相似的单个条目。
GraphRAG 和 HippoRAG 表明,在查询时对知识图谱运行小规模个性化 PageRank,可以显著改善多跳检索。hubmesh 在此基础上做出了两项改进:
- 以实体为锚点进行播种,采用多组件排序。 在 KG 模式下,PPR 的种子是从语料库图谱中解析出的查询实体(通过别名索引;如果查询中没有实体,则回退到余弦相似度最高的匹配项中的实体);在 kNN 模式下,种子则是 ANN top-k。多组件评分——余弦相关性、汇总 PPR 权重以及多锚点收敛度,经过 min-max 归一化后按 3:1:1 融合——作用于文档排序,而非种子选择。
- 感知预算的上下文打包。 对相关实体评分后,将其打包到大模型的上下文窗口中,并明确控制覆盖范围和冗余,而不是简单截断 top-k。
这种多组件评分模式改编自用于 SDN 拓扑优化的 NNSI 框架(Naidu et al., CCIS 2934, Springer, 2026),并在此用于检索规划。
快速开始
内存模式(测试、小型语料库)
from hubmesh import Planner
from hubmesh.adapters import InMemoryStore
embed = ... # callable: text -> np.ndarray
docs = [...] # list of Document or strings or dicts
store = InMemoryStore.from_documents(docs, embed=embed)
planner = Planner(store=store, embed=embed)
result = planner.retrieve(query="...", top_k=10, budget_tokens=4000)
Qdrant 适配器(生产环境)
from hubmesh import Planner
from hubmesh.adapters import QdrantStore
store = QdrantStore.from_documents(docs) # in-memory
store = QdrantStore.from_documents(docs, path="./qdrant_data") # on-disk
store = QdrantStore.from_documents(docs, url="http://localhost:6333") # remote
planner = Planner(store=store, embed=embed)
result = planner.retrieve(query="...", top_k=10)
Chroma 适配器
from hubmesh.adapters import ChromaStore
store = ChromaStore.from_documents(docs) # ephemeral
store = ChromaStore.from_documents(docs, persist_directory="./chroma_data")
store = ChromaStore.from_documents(docs, host="localhost", port=8000)
多跳 / KG 模式
from hubmesh.kg import build_entity_kg
import spacy
nlp = spacy.load("en_core_web_sm")
kg = build_entity_kg(docs, nlp=nlp)
planner = Planner(store=store, kg=kg, nlp=nlp, embed=embed) # embed= needed for text queries
result = planner.retrieve(query="Where was the founder of the company that bought Slack born?",
top_k=10, budget_tokens=4000)
# RetrievalResult includes reasoning paths showing why each doc was returned
for path in result.reasoning:
print(f" score={path.score:.3f} {' → '.join(path.node_ids)}")
LLM 提取的 KG(比 spaCy 更丰富)
from hubmesh.kg_llm import build_entity_kg_llm
from hubmesh.entity_linker import EmbeddingLinker, make_st_embedder
def llm(prompt): # provider-agnostic — bring your own
return your_llm_call(prompt)
kg = build_entity_kg_llm(docs, llm=llm, cache_path="kg_cache.json")
# optional: cross-document entity dedup — same Linker protocol as the spaCy path
kg = build_entity_kg_llm(docs, llm=llm, cache_path="kg_cache.json",
linker=EmbeddingLinker(embed=make_st_embedder()),
llm_identity="gpt-5-mini") # namespaces the cache
planner = Planner(store=store, kg=kg, nlp=nlp, embed=embed)
更好的实体链接
from hubmesh.kg import build_entity_kg
from hubmesh.entity_linker import EmbeddingLinker, make_st_embedder
# Cluster surface variations: "United States" / "U.S." / "USA" → one entity
linker = EmbeddingLinker(embed=make_st_embedder(), threshold=0.82)
kg = build_entity_kg(docs, linker=linker)
迭代式多跳:让你的 Agent 来驱动
r1 = planner.retrieve(query=question, top_k=5)
# your agent reads r1, spots the bridge entity, then aims hop 2 at it:
r2 = planner.retrieve(
query=question, top_k=5,
seed_entities=["Nimbus Analytics"], # merged with the query's own seeds
exclude_docs=[s.doc.id for s in r1.sources], # don't re-retrieve consumed docs
)
种子提及会通过别名索引解析,因此可以使用自由文本实体名称。查询路径保持确定性,不依赖 LLM——规划智能由调用方提供。
MCP 服务:将 hubmesh 接入任意 Agent
pip install "hubmesh[mcp]"
python -m spacy download en_core_web_sm
{"mcpServers": {"hubmesh": {"command": "hubmesh-mcp"}}}
通过 stdio 将规划器作为确定性操作工具暴露出来——
index_corpus、retrieve(可通过种子引导,如上所述)、resolve_entities、
entity_neighbors、path_between、get_document、graph_stats、
list_corpora。你的 Agent 负责求解:它会拆解问题、
读取每一步,并确定下一步的方向;服务则在几毫秒内作答,
且不会调用任何大模型。语料库以纯 JSON/NPZ 格式
持久化在 ~/.hubmesh/corpora 下。
服务会在启动时于后台预热模型并加载持久化语料库 (首次运行约需 5-10 秒),因此工具调用从一开始就能保持快速—— 这对有严格超时限制的连接器客户端(Perplexity 等)很重要。
对于基于 Web 的连接器客户端,可原生提供 SSE 服务——无需网关 进程:
export HUBMESH_API_KEY="$(openssl rand -hex 24)" # any strong secret
hubmesh-mcp --transport sse --port 8000 --allow-tunnel
ngrok http 8000 # paste https://<your-url>/sse into the connector
通过隧道提供服务必须使用 API key(没有 API key,服务会拒绝启动),
且默认采用只读模式——传入 --allow-writes 可保持 index_corpus 启用。客户端必须发送
Authorization: Bearer <key>。如果你的连接器客户端无法设置
请求头,隧道边缘必须在添加上游请求头之前自行对调用方进行身份验证
(ngrok OAuth / IP 限制流量策略、Cloudflare Access,……)。对于匿名
流量注入请求头,会让所有调用方都获得完整的读取权限(只读模式能防止语料库
被替换,但无法防止信息泄露;get_document 会返回完整
文本)。既无法发送请求头、又无法通过具备身份验证功能的边缘进行连接的客户端,不支持访问私有语料库。
隧道使用说明(来自一次正在运行的 Perplexity 集成):ngrok 可用
(包括免费套餐);cloudflared 快速隧道会缓冲 SSE 正文
并导致工具调用挂起;这里不需要 supergateway,且它会在重新连接时崩溃。
--allow-tunnel 会接受隧道转发的 Host 请求头——如果不使用该选项,
代理请求会得到 421 Misdirected Request。
完整的实测报告——包括设置说明、错误解码器、通过 Perplexity 运行的 9/9 测试套件,以及关于推理模型行为的两项发现——详见 docs/perplexity.md。
长文档分块处理
from hubmesh import chunk_by_sentences, chunk_documents
chunks = chunk_documents(
[{"id": "doc1", "text": long_text}, ...],
strategy="sentences", target_tokens=200,
)
# Then embed chunks and index normally
安装
pip install hubmesh # core
pip install "hubmesh[qdrant]" # Qdrant adapter
pip install "hubmesh[chroma]" # Chroma adapter
pip install "hubmesh[kg]" # entity-linked KG (spaCy)
pip install "hubmesh[linker]" # embedding-based entity linker
pip install "hubmesh[all]" # everything
python -m spacy download en_core_web_sm # required for KG mode
设计
KG 模式——经过基准测试的生产路径:
query ─► spaCy NER ─► alias index ─► entity seeds ─► Personalized PageRank over the corpus KG
│ (fallback: entities of the top-3 cosine documents) │
└───────────► cosine similarity against every document ─────────────────────────────┤
▼
3·minmax(cosine) + 1·minmax(pooled PPR) + 1·minmax(per-anchor geomean) [weighted sum]
▼
budget-aware packing ─► context + sources + reasoning paths
kNN 模式(无 KG;用于原型设计):第一阶段使用 ANN → 构建有上限的诱导邻近 子图 → 从 ANN 种子执行 PPR → 使用相同的评分和打包流程。 社区锚定功能适用于单主题检索,默认关闭。
每一层都可独立测试和替换。适配器会封装你现有的 向量数据库,因此无需迁移——请注意,KG 模式会对每个文档评分(每个存储版本只收集一次向量 并缓存),且仅在种子回退时使用存储的 ANN 索引。
基准测试
在合并的干扰段落语料上评估支持事实段落召回率。每一行都是一项独立实验:文档表示方式和嵌入模型会显著改变绝对数值,因此不同表示方式的结果不可横向比较。协议、消融实验和限制见 BENCHMARKS.md。
完整 HotpotQA dev(7,405 个问题,66,581 个合并段落),hubmesh 对比朴素余弦,v0.4 默认设置:
| 表示方式 · 嵌入模型 | 朴素 @10 | hubmesh @10 | Δ @10 | Δ @5 | Δ @2 |
|---|---|---|---|---|---|
| 仅正文 · MiniLM-L6 | 69.3% | 75.2% | +5.90 | +4.21 | −0.75 |
| 标题+正文 · MiniLM-L6 | 70.0% | 77.3% | +7.24 | +5.88 | +0.25 |
| 标题+正文 · bge-m3 | 83.5% | 84.8% | +1.38 | −1.41 | −9.09 |
需要双向解读。使用较小的嵌入模型时,图层可将深层召回率提高 5–7 个百分点;使用强模型时,深层召回率的提升缩小到 +1.4,而默认设置会损害排名靠前的结果(recall@2 时 −9.1)。收敛项以牺牲排名靠前结果的精度来换取深层召回率:对于使用强嵌入模型、关注 top-2/top-5 的工作负载,请使用 use_convergence=False 或纯余弦,并先在自己的工作负载上评估,再决定是否全面启用图层。
**完整 MuSiQue-Ans dev(2,417 个问题,MiniLM,仅正文),hubmesh 对比朴素方法,recall@10 及配对 95% CI:**总体 +3.67 [+3.00, +4.39](@2 时 +2.2,@5 时 +3.3);按跳数分别为 +2.9 / +4.1 / +5.3(n = 1,252 / 760 / 405)。增益随跳数增加;在 MuSiQue 上,hubmesh 在 recall@2 上也优于朴素方法。
评分带来的提升(HotpotQA N=500,仅正文,recall@10):在同一图、种子、回退机制和打包器上,余弦融合评分达到 0.871,纯结构信号(仅 PPR)为 0.676——+19.5 个百分点 [+16.3, +22.7](MuSiQue N=300:+16.3)。早期版本曾引用与 HippoRAG 风格排序器对比的 +29.8;该对比也改变了处理流程,因此不再将其归因于评分。
**收敛项(默认开启):**在完整 MuSiQue dev 上,相比关闭收敛,@10 提升 +0.9 个百分点;在 HotpotQA N=500 上提升 +1.1。相同位置使用单次求解的对数池化信号,整体表现与之相当;在三跳和四跳时,几何均值仍保留约 1 个百分点的提升。多种子查询的成本约为 1.5–2×(仍不消耗 LLM token,且结果确定)。
延迟:在 7K 节点的 KG 上,每个查询平均约 22 ms,p95 为 26 ms(PPR 矩阵缓存后)。在完整开发集的 66K 段落规模下,曾测得开启收敛时约 3 秒/查询;该测量是在移除每个查询的向量重新收集之前进行的。此后尚未重新测量该规模。
复现(每次运行都会写入一个 JSON,包含逐查询记录和清单;清单记录 commit、dirty 标志以及源代码/测试框架内容哈希):
python benchmarks/run_hotpotqa.py --n 500 --kg --out hotpot.json
python benchmarks/run_musique.py --n 300 --kg --out musique.json
python benchmarks/run_ablation_coherence.py --dataset musique --n 2417
python benchmarks/profile_query.py # latency profile
状态
预 alpha(v0.4.2)。核心算法已实现并验证;提供内存、Qdrant 和 Chroma 适配器;实体关联 KG 支持 spaCy NER 和基于 LLM 的抽取(两者都能感知链接器);基于别名索引的实体消歧;NNSI-KG 评分(默认开启多源收敛,可选启用 hub 折扣 PPR);由 Agent 驱动的迭代式多跳检索,通过 seed_entities / exclude_docs 实现;MCP 操作员服务(hubmesh-mcp,原生 SSE),支持 JSON/NPZ 语料持久化;文档分块;推理路径解释;PPR 缓存延迟优化。Pinecone / pgvector / Weaviate 适配器和更多多跳基准测试列为适合新手的首批议题。
致谢
多组件评分模式改编自以下文献介绍的 Network Node Significance Index (NNSI) 框架:
D. S. K. Naidu 等,“基于软件定义网络中的图论改进网络拓扑的框架”,载于 Internet Computing, Internet of Things, Artificial Intelligence, and Applications,Communications in Computer and Information Science,第 2934 卷,H. R. Arabnia、L. Deligiannidis、 K. Ferens、F. Ghareh Mohammadi、F. Shenavarmasouleh 和 S. Amirian 编。 Cham:Springer,2026 年,第 3–18 页。 doi:10.1007/978-3-032-22190-2_1
@inproceedings{naidu2026nnsi,
author = {Naidu, Datta Sai Krishna and others},
title = {A Framework for Improving Network Topology Based on Graph Theory
in Software-Defined Networking},
booktitle = {Internet Computing, Internet of Things, Artificial Intelligence,
and Applications},
series = {Communications in Computer and Information Science},
volume = {2934},
editor = {Arabnia, Hamid R. and Deligiannidis, Leonidas and Ferens, Ken and
Ghareh Mohammadi, Farid and Shenavarmasouleh, Farzan and
Amirian, Soheyla},
pages = {3--18},
publisher = {Springer},
address = {Cham},
year = {2026},
doi = {10.1007/978-3-032-22190-2_1},
isbn = {978-3-032-22189-6}
}
本文将 NNSI 从 SDN 拓扑优化改用于检索规划;将其应用于基于实体链接的 KG 检索是本研究的新内容。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。