继上文《深度解析仿人脑记忆搜索的HippoRAG2》,我们已经对HippoRAG2有了基本的了解。本篇将更聚焦于实践部分,探讨如何配置和运行HippoRAG2,包括测试评估和索引自定义文档和数据,并分析其成本与运行时间。最后,我们将索引小说《仙逆》,并与我们早期测试GraphRAG的文章《实战微软新一代RAG》在相同问题上的表现进行对比。
由于 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
去除上述配置后,整个世界都安静了,一个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"
)
配置已经完成,我们开始索引。索引采用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万。
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
hipporag2的查询方法目前只支持一组查询语句,因此我们参考文章《实战GraphRAG》的测试问题集,对《仙逆》进行查询。
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: 王林的经历包括离家出走、被救回、参加选拔、坚持测试、剑灵测试和攀爬石阶。
从问答效果来看,前面三个问题回答都是对的,而当时GraphRAG没能回答正确关于王林和铁柱的关系。而HippoRAG不仅解释了是他的小名,还解释了小名的由来,回答比较完整和丰富。
我们在看第4个问题,这其实是一个全局类的问题,HippoRAG除了描述的事情的经过,它还按照顺序描述了出来,可以说非常不错。
如果你要评估,你需要设计数据集。评估数据集要按照这个形式设计
[
{
"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)
本文介绍了 HippoRAG2 的安装、配置、索引、查询及评估流程,并与 GraphRAG 进行了对比测试。后续我们将继续深入优化HippoRAG2,直到能够简单使用~
关注我,获得第一时间更新~