前言:
GraphRAG 是一种结合了知识图谱和检索增强生成(RAG)的技术,旨在提升大型语言模型(LLM)处理复杂信息的能力。。
Ollama 是一个开源的工具,它允许用户在本地环境中轻松地运行和定制大型语言模型(LLM)。
在这里,我用一张自己画的框架图尝试解释:
由于工作原因,哈某需要部署一个基于知识图谱的本地化大模型增强检索方案。在查阅了大量方案之后,选中了微软最近开源的GraphRAG项目,提供了一种较为整合的方案代码。当然也有其他方案,如基于本地大模型+LangChain+Neo4j等方案,碍于篇幅本文不作详细介绍,感兴趣可以看看我后续写的相关文章。
但是基于研发技术栈背景是Java的缘故,花了几天时间学了Python,并对官方代码做了修改以适配Ollama(原生代码仅仅支持OpenAI,因为微软官方工作重点更多在生成方案上而非适配多种大模型),作为这个领域的初学者,我会用更接近P模式的方式,尽可能深入浅出的介绍方案。
1.首先使用命令拉取GraphRag官方代码(哈某的python环境是3.12)
pip install graphrag
执行命令后,将会获得graphrag的项目源码,也可以通过git的方式获取,在这里不多做赘述,获取后就可以通过Pycharm、Vscode等打开项目了。
2.初始化项目(在项目目录下启动终端进行命令操作)
python -m graphrag.index --init --root ./{替换你自己的目标文件夹}moon
执行命令后这里将会建立目标文件夹,自动生成配置文件、默认prompts提示词工程文件夹等。我们后续所有操作的知识库源数据、生成的图数据、中间缓存、日志文件、位置文件等都将在这里进行。
3.在目标文件夹下建立input文件夹
我们需要在{目标文件夹}中建立input文件夹用于存放知识源文件,目前GraphRAG支持csv、txt等文件,哈某在这里使用《小王子》的txt文件为例。
4.修改openai_embeddings_llm.py文件中代码以适配本地大模型
因为GraphRAG官方的工作更多在于检索增强方案的设计开发,目前还没有对模型的适配做太多工作,所以需要将原本代码中与OpenApi适配的接口方案替换为Ollama的。修改方案就是注释掉原本代码中适配方案,导入并替换为ollama的(已在代码中注明,可直接复制粘贴全部代码)
注意embedding = ollama.embeddings(model="quentinz/bge-large-zh-v1.5:latest", prompt=inp)这一行,实现了对Ollama中模型的接入和选择,所以需要在这里手动选定Ollama中要用到的嵌入模型,哈某在这里用了quentinz/bge-large-zh-v1.5:latest的,大家根据自己需求自行选择。这里不能仅仅在配置文件中作修改限定。
# Copyright (c) 2024 Microsoft Corporation.
# Licensed under the MIT License
"""The EmbeddingsLLM class."""
import ollama
from typing_extensions import Unpack
from graphrag.llm.base import BaseLLM
from graphrag.llm.types import (
EmbeddingInput,
EmbeddingOutput,
LLMInput,
)
from .openai_configuration import OpenAIConfiguration
from .types import OpenAIClientTypes
class OpenAIEmbeddingsLLM(BaseLLM[EmbeddingInput, EmbeddingOutput]):
"""A text-embedding generator LLM."""
_client: OpenAIClientTypes
_configuration: OpenAIConfiguration
def __init__(self, client: OpenAIClientTypes, configuration: OpenAIConfiguration):
self.client = client
self.configuration = configuration
async def _execute_llm(
self, input: EmbeddingInput, **kwargs: Unpack[LLMInput]
) -> EmbeddingOutput | None:
args = {
"model": self.configuration.model,
**(kwargs.get("model_parameters") or {}),
}
# embedding = await self.client.embeddings.create(
# input=input,
# **args,
# )
# return [d.embedding for d in embedding.data]
embedding_list = []
for inp in input:
embedding = ollama.embeddings(model="quentinz/bge-large-zh-v1.5:latest", prompt=inp)
embedding_list.append(embedding["embedding"])
return embedding_list
4.修改embedding.py文件中代码以适配本地大模型
原代码中_embed_with_retry和_aembed_with_retry方法使用self.sync_client和self.async_client来调用OpenAI的同步和异步嵌入创建方法。这些方法依赖于 OpenAI 的 API 客户端来生成嵌入。
需要修改为被修改为使用OllamaEmbeddings类来生成嵌入。代码将会依赖于langchain_community.embeddings模块中的OllamaEmbeddings类,这是一个用于与 Ollama 服务交互的包装器。
原代码:
embedding = (
self.sync_client.embeddings.create( # type: ignore
input=text,
model=self.model,
**kwargs, # type: ignore
)
.data[0]
.embedding
or []
)
修改为:
embedding = (
OllamaEmbeddings(
model=self.model,
).embed_query(text)
or []
)
原代码:
embedding = (
await self.async_client.embeddings.create( # type: ignore
input=text,
model=self.model,
**kwargs, # type: ignore
)
).data[0].embedding or []
修改为:
embedding = (
await OllamaEmbeddings(
model=self.model,
).embed_query(text) or [] )
5.构建Graph索引
python -m graphrag.index --root ./{替换你自己的目标文件夹}moon
6.执行查询(分为局部查询和总体查询两种)
# global query
python -m graphrag.query \
--root ./{替换你自己的目标文件夹}moon \
--method global \
"{替换你自己的问题}小王子是谁?"
# local query
python -m graphrag.query \
--root ./{替换你自己的目标文件夹}moon \
--method local \
"{替换你自己的问题}小王子是谁?"
通过以上,就实现了GraphRAG当中对知识图谱的构建和对本地化Ollama的适配改造,并可以进行检索增强的提问方案。
写在最后:哈某是为了学习开发这个项目,临时突击学习了python的相关知识,期间借鉴学习了不少大佬的教程课程,非常感谢。但是仍然存在不少漏洞,如果有问题,还请指出和多多包涵,我会立刻进行改进。您的建议和意见都十分宝贵,感谢!
另外,目前我和朋友们在尝试将GraphRAG、RAG、知识图谱和LangChain结合,参考LangChain4J、SpirngAI、AIAlibaba、Dity等,在尝试开发Java版本大模型框架(开源项目已开放至GitHub),发现当前阶段无论是大模型本身的基座能力、还是增强检索的方案,都存在一定缺陷。甚至存在不平衡三角问题。目前对于回答质量这个单一目标而言,依然可以认为是GIGO原则,也就是“垃圾进,垃圾出”。我们仍在在努力,也非常期望有更多伙伴提供宝贵意见或者加入到我们当中来。