继上文《深度解析仿人脑记忆搜索的 HippoRAG2》,我们已经对 HippoRAG2 有了基本的了解。本篇将更聚焦于实践部分,探讨如何配置和运行 HippoRAG2,包括测试评估和索引自定义文档和数据,并分析其成本与运行时间。最后,我们将索引小说《仙逆》,并与《实战微软新一代 RAG》在相同问题上的表现进行对比。
1. 安装与环境配置
由于 HippoRAG2 刚刚开源,目前仍以源码运行为主。该项目以科研为目的,且不像微软那样具有广泛的社区支持,因此短期内不太可能提供生产级(production-ready)的实现。按照 HippoRAG1 的发展趋势,未来的优化可能较为有限。 首先,克隆 HippoRAG2 并安装:
pip install https://github.com/OSU-NLP-Group/HippoRAG
创建 Python 3.10 的 Conda 虚拟环境:
conda create -n hippo python=3.10
安装依赖:
pip install -r requirements.txt
然后你会发现,它还需要安装vllm
、torch
、gritlm
和transformers
等大型依赖。多说一句,后面还需要使用transformer
运行HuggingFace
上的7B Embedding
服务,而这个是 FP16 的模型,需要至少 14G 的显存,所以如果你本地显卡不行,官方源码你可能无法运行。到这我估计到这很多人就要被劝退了,但作为一名经验丰富的技术博主,必须魔改代码,去除上述所有依赖,大模型和 Embedding 必须可以配置 OpenAI 兼容的远程服务。魔改代码在最后~。
完整依赖列表如下:
gritlm==1.0.2
networkx==3.4.2
numpy==2.2.1
openai==1.58.1
pydantic==2.10.4
python_igraph==0.11.8
scipy==1.14.1
tenacity==8.5.0
tiktoken==0.7.0
torch==2.4.0
tqdm==4.66.6
vllm==0.6.6.post1
transformers==4.45.2
nest_asyncio
dspy==2.5.29
einops
2. 配置优化
去除上述配置后,整个世界都安静了,一个 RAG 应用安装 vllm 是不是太搞笑了?去除上述本地依赖后,我们可以改为使用远程大模型 API 和嵌入(Embedding)服务,从而降低本地计算资源的消耗。 首先,进行基本配置,其中 BaseConfig 已经更新支持配置远程模型。大模型配置我们钟爱的 DeepSeek V3,Embedding 使用硅基流动的免费 bge-m3。但按照《上文》所说,这里最好是使用 7B 左右的大语言模型支持的 Emebdding 模型,以便于消歧。
from hipporag.utils.config_utils import BaseConfig
config = BaseConfig(
llm_base_url="https://api.deepseek.com/v1",
llm_name='deepseek-chat',
llm_api_key="sk-xxxx",
embedding_api_base="https://api.siliconflow.cn/v1",
embedding_api_key="sk-xxx",
embedding_model_name='BAAI/bge-m3',
embedding_batch_size=16,
rerank_dspy_file_path="hipporag/prompts/dspy_prompts/filter_llama3.3-70B-Instruct.json",
graph_type="facts_and_sim_passage_node_unidirectional",
max_new_tokens=4096,
openie_mode="online"
)
3. 索引
配置已经完成,我们开始索引。索引采用HippoRAG().index()
进行索引,接收的输入为字符串数组:
def index(self, docs: List[str]):
pass
从源码来看,docs
数组在index
中并不会自动进行chunk
分割,因此我们需要先编写一个文本分割方法。例如:
def split_text_by_tokens(file_path: str, max_tokens: int = 512, overlap: int = 100) -> list[str]:
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
...
while start < len(tokens):
end = min(start + max_tokens, len(tokens))
chunk_tokens = tokens[start:end]
chunks.append(enc.decode(chunk_tokens))
start += max_tokens - overlap
return chunks
接下来,对小说《仙逆》的前 10 章进行分割:
docs = chunk.split_text_by_tokens("input/xianni.txt")
实例化 HippoRAG 并执行索引:
from hipporag import HippoRAG
save_dir = 'outputs/xianni' # 指定输出目录
hipporag = HippoRAG(save_dir=save_dir, global_config=config)
hipporag.index(docs=docs)
输入文件大约 31000 个 Token 左右,索引耗时 10 分钟左右,耗费 Tokens 数量 8 万。
image-20250303224849656
Hipporag2 自带缓存,抽取的 NER 等操作都已经自动缓存了,只要文件不变,它会自动利用缓存,第二次索引时间几乎为 0,反复跑 index 是没问题的。
索引后的文件就在我们设置的save_dir
下,包含chunk_embedding
、entity_embedding
和fact_embedding
3 部分,以及graphml
图存储和openie
结果,如下所示:
├── deepseek-chat_BAAI_bge-m3
│ ├── chunk_embeddings
│ │ └── vdb_chunk.parquet
│ ├── entity_embeddings
│ │ └── vdb_entity.parquet
│ ├── fact_embeddings
│ │ └── vdb_fact.parquet
│ └── graph.graphml
├── llm_cache
│ ├── deepseek-chat_cache.sqlite
│ └── deepseek-chat_cache.sqlite.lock
└── openie_results_ner_deepseek-chat.json
4. 查询
hipporag2 的查询方法目前只支持一组查询语句,因此我们参考文章《实战微软新一代 RAG》的测试问题集,对《仙逆》进行查询。
all_queries = ["谁是王林 他的主要人际关系是什么样",
"王林和铁柱的关系",
"王林的小名是什么",
"在这个故事中王林的经历有哪些"]
查询方式如下:
- 先检索后回答
retrieval_results = hipporag.retrieve(queries=all_queries)
ret = hipporag.qa(retrieval_results)
- 直接生成答案
hipporag.rag_qa(queries=retrieval_results)
ret = hipporag.rag_qa(queries=all_queries)
示例回答:
- 谁是王林 他的主要人际关系是什么样
王林的本名是王林,小名叫铁柱。他是王氏家族的一员,父亲是家族内庶出的次子,母亲对他非常关心。王林从小聪明,喜欢读书,是村子内公认的神童,父母对他期望很高。他的主要人际关系包括:
- 父亲:对王林寄予厚望,经常听到别人夸奖王林时会露出开怀的微笑。
- 母亲:对王林关心有佳,从小生活在父母的慈爱之中。
- 亲戚:包括三祖父、四叔等,三祖父曾暗中帮助过王林的父亲,四叔在家族中维护王林和他父亲。
- 王天山:王林的亲戚,与王林父亲有矛盾,曾冷嘲热讽王林。
- 王卓:王林的亲戚,傲慢不逊,对王林表现出轻蔑。 Answer: 王林是王氏家族的一员,小名叫铁柱。他的主要人际关系包括父亲、母亲、三祖父、四叔、王天山和王卓。
- 王林和铁柱的关系
根据文本内容,王林的本名是王林,而“铁柱”是他的小名。因此,王林和铁柱是同一个人,铁柱是王林的称呼。
Answer: 王林和铁柱是同一个人,铁柱是王林的小名。
- 王林的小名是什么。
王林的小名是铁柱。根据文本描述,铁柱是他的小名,因为从小身体瘦弱,父亲怕养不活,于是按照习俗称呼他为铁柱。
Answer: 铁柱。
- 在这个故事中王林的经历有哪些
在这个故事中,王林的经历包括以下几个主要事件:
- 王林离家出走,试图自杀,但被天然形成的风眼吸扯,因此没有摔死。
- 他被张姓弟子找到并带回恒岳派,与母亲相见,了解了事情的经过。
- 王林被四叔带走,前往县城参加家族的选拔,离开了居住十五年的山村。
- 在恒岳派的测试中,王林坚持到最后,尽管身体受伤严重,但他没有放弃。
- 王林和其他坚持到最后的少年被送到剑灵阁进行剑灵测试,尽管心灵受到创伤,但他仍然坚持。
- 在攀爬石阶的过程中,王林全身受伤,但他仍然坚持用手攀爬,表现出极强的毅力和决心。
Answer: 王林的经历包括离家出走、被救回、参加选拔、坚持测试、剑灵测试和攀爬石阶。
从问答效果来看,前面三个问题回答都是对的,而当时 GraphRAG 没能回答正确关于王林和铁柱的关系。而 HippoRAG 不仅解释了是他的小名,还解释了小名的由来,回答比较完整和丰富。
我们在看第 4 个问题,这其实是一个全局类的问题,HippoRAG 除了描述的事情的经过,它还按照顺序描述了出来,可以说非常不错。
5. 评估
如果你要评估,你需要设计数据集。评估数据集要按照这个形式设计
[
{
"id": "sample/question_1.json",
"question": "Which Stanford University professor works on Alzheimer's?",
"answer": [
"Thomas C. Sudhof"
],
"answerable": true,
"paragraphs": [
{
"title": "Thomas C. Sudhof",
"text": "Introductio...",
"is_supporting": true,
"idx": 0
}
]
}
]
评估方法如下,会在回答完成后自动完成 EM 和 F1 评分计算。
gold_docs = get_gold_docs(samples, dataset_name)
gold_answers = get_gold_answers(samples)
hipporag.rag_qa(queries=all_queries, gold_docs=gold_docs, gold_answers=gold_answers)
6. 代码获取
我已经针对 HippoRAG2 进行了配置优化,去除了冗余依赖,支持中文,让你可以轻量级部署,抢先轻松上手。本文优化的代码和文中出现的测试代码都已经上传我的知识星球。而且,我还会持续更新优化策略,提供实战经验、代码解析和技术答疑!立即加入我的知识星球AgenticLM,一起探索最前沿的 RAG 技术,抢先体验 HippoRAG 2。
总结
本文介绍了 HippoRAG2 的安装、配置、索引、查询及评估流程,并与 GraphRAG 进行了对比测试。后续我们将继续深入优化 HippoRAG2,直到能够简单使用~