前些日子微软开源了 GraphRAG ,使用知识图谱加强了大模型回答总结性问题的能力,我很想探索调试一下它的源码。
但是听朋友说,这玩意是是个 吞金兽,随便运行一篇短小的文档需要花费几十美刀(调用 OpenAI 接口的花费),便作罢。
仔细想想,又觉得不对劲,现在小模型已经很发达了,使用 Ollama 可以直接在自己的笔记本上部署 lamma3 8B,mistra 7B,qwen2 7B 等各式各样的小模型,运行效果也都还可以。
直接把接口换成这些本地模型,不就可以直接在自己电脑上调试了?
还没来得及干,便发现了一条类似的 Issue,发现已经有人完事了,就是 graph-local-ollama。那还等什么,直接用它开干。
准备素材:
- 自己的笔记本电脑:最好有独显,没有也可以,但是要控制输入文档大小,不然电脑容易死机
- VSCode:用来 Debug 源码,个人更喜欢用 VSCode 调试 Python 代码,相比 PyCharm 更加轻便快速
读者将可以:
- 本地执行 GraphRAG,将任意文档生成一个 3D 知识图谱,并通过它进行问答
- 在 VSCode 上单步调试 GraphRAG,方便进一步探索
第一步 本机安装 ollama
对于 mac,从 官网 直接下载安装包安装即可,基本没啥坑。
对于有独显的计算机,可能因为英伟达驱动和 cuda 版本太低,导致显卡未能利用。
我在自己的一台带独显的 Linux 服务器上,发现 Ollama 后台服务执行时会有如下报错信息,导致显卡未检测到:
symbol lookup for cuCtxCreate_v3 failed
在 Linux 上,Ollama 由一个前端命令行和一个后台 systemd 守护进程组成,通过
sudo journalctl -u ollama.service能够看到 Ollama 后台守护进程的日志,看到这个报错
我原本机器上的显卡驱动版本是 450,cuda 版本是 11.0。驱动升级到 510,cuda 升级到 11.6 后才解决该问题。参考issue
sudo apt install nvidia-driver-510
启动 Ollama 后台服务时(systemctl restart ollama),用 sudo journalctl -u ollama.service 看到如下信息,才说明成功检测到显卡:
第二步 使用 ollama 下载需要的模型
ollama pull mistral #llm
ollama pull llama3.1
ollama pull nomic-embed-text #embedding
验证下是否可用:
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "mistral",
"messages": [
{
"role": "system",
"content": "你熟读西游记"
},
{
"role": "user",
"content": "西游记中孙悟空和猪八戒的关系是什么?"
}
]
}'
第三步 新建一个专用的 conda 环境
GraphRAG 建议的 Python 版本是 3.10~3.12,为了和本地的其他 Python 环境隔离,专门新建一个 conda 环境。conda 安装就不详述了,参考。
conda create -n graphrag-env python=3.10
conda activate graphrag-env
将 graph-local-llama 下载下来并安装所需要的包:
git clone https://github.com/TheAiSingularity/graphrag-local-ollama.git
cd graphrag-local-ollama/
pip install -e .
pip install future
pip install ollama
第四步 初始化工作目录
GraphRAG 需要一个工作目录,这里创建并对其初始化。在 graphrag-local-ollama 项目目录下执行以下操作。
创建工作目录:
mkdir -p ./ragtest/input
将需要生成知识图谱的文档复制进去,这里用的是项目自带的,也可以换成自己喜欢的:
cp input/* ./ragtest/input
如果机器上没有独显的话,建议只截取一个小段落放进去。我在 16G 内存的 mac 上尝试跑这些文档,直接死机了
初始化目录:
python -m graphrag.index --init --root ./ragtest
将配置文件拷贝去工作目录,并且改一改:
cp settings.yaml ./ragtest
修改 settings.yaml 可以更换模型的种类,获取去请求远程带独显的 ollama:
encoding_model: cl100k_base
skip_workflows: []
llm:
api_key: ${GRAPHRAG_API_KEY}
type: openai_chat # or azure_openai_chat
# 修改模型种类,以 ollama list 中列出的模型名称为准
model: mistral
model_supports_json: true # recommended if this is available for your model.
# 默认请求本地 ollama,可以改成远程的带独显机器,性能更好
api_base: http://localhost:11434/v1
第五步 生成知识图谱
执行以下命令生成知识图谱:
python -m graphrag.index --root ./ragtest
这个过程很难一番风顺,比如电脑性能太过弱鸡,三次请求重试都没有成功,整个流程就跪了,在 ./ragtest/${运行开始时间}/reports/indexing-engine.log 中可以看到报错信息:
再比如,我曾经尝试用 llama3.1 而不是 mistral,结果 llama3.1 总是无法生成合法的 Json,导致 parse 一直失败。所以本地小模型的调试还是建议老老实实用 mistral。
生成的知识图谱位于 ragtest/output/${执行时间}/artifacts/summarized_graph.graphml,使用 graphml 格式表示的,可以用 Gephi 查看,不过我尝试了一下,体验相当糟糕。好在作者又给我们准备了一个 graphml 查看脚本,就是项目目录的 visualize-graphml.py,将脚本中的 graphml 路径改成自己的就可以了。
不过原本作者的脚本是用浅色背景展示的,看起来有点费眼,我优化了一版,采用深色背景, 连线看起来会更加清晰:
import networkx as nx
import plotly.graph_objects as go
import numpy as np
# Load the GraphML file
# 改成自己的文件路径
graph = nx.read_graphml('ragtest/output/20240908-014352/artifacts/summarized_graph.graphml')
# Create a 3D spring layout with more separation
pos = nx.spring_layout(graph, dim=3, seed=42, k=0.5)
# Extract node positions
x_nodes = [pos[node][0] for node in graph.nodes()]
y_nodes = [pos[node][1] for node in graph.nodes()]
z_nodes = [pos[node][2] for node in graph.nodes()]
# Extract edge positions
x_edges = []
y_edges = []
z_edges = []
for edge in graph.edges():
x_edges.extend([pos[edge[0]][0], pos[edge[1]][0], None])
y_edges.extend([pos[edge[0]][1], pos[edge[1]][1], None])
z_edges.extend([pos[edge[0]][2], pos[edge[1]][2], None])
# Generate node colors based on a colormap
node_colors = [graph.degree(node) for node in graph.nodes()]
node_colors = np.array(node_colors)
node_colors = (node_colors - node_colors.min()) / (node_colors.max() - node_colors.min()) # Normalize to [0, 1]
# Create the trace for edges
edge_trace = go.Scatter3d(
x=x_edges, y=y_edges, z=z_edges,
mode='lines',
line=dict(color='lightgray', width=0.5),
hoverinfo='none'
)
# Create the trace for nodes
node_trace = go.Scatter3d(
x=x_nodes, y=y_nodes, z=z_nodes,
mode='markers+text',
marker=dict(
size=7,
color=node_colors,
colorscale='Viridis', # Use a color scale for the nodes
colorbar=dict(
title='Node Degree',
thickness=10,
x=1.1,
tickvals=[0, 1],
ticktext=['Low', 'High']
),
line=dict(width=1)
),
text=[node for node in graph.nodes()],
textposition="top center",
textfont=dict(size=10, color='white'),
hoverinfo='text'
)
# Create the 3D plot
fig = go.Figure(data=[edge_trace, node_trace])
# Update layout for better visualization
fig.update_layout(
title='3D Graph Visualization',
showlegend=False,
scene=dict(
xaxis=dict(showbackground=False, backgroundcolor='black', color='white', gridcolor='gray'),
yaxis=dict(showbackground=False, backgroundcolor='black', color='white', gridcolor='gray'),
zaxis=dict(showbackground=False, backgroundcolor='black', color='white', gridcolor='gray')
),
paper_bgcolor='black',
plot_bgcolor='black',
margin=dict(l=0, r=0, b=0, t=40),
annotations=[
dict(
showarrow=False,
text="Interactive 3D visualization of GraphML data",
xref="paper",
yref="paper",
x=0,
y=0,
font=dict(color='white')
)
]
)
# Show the plot
fig.show()
执行前先安装 plotly:
pip install plotly
之后直接执行该脚本:
python visualize-graphml.py
浏览器会自动弹出并展示结果:
也可能没那么顺利,浏览器弹出一个报错:
此时只要打开 Chrome 的图形加速就好了:
第六步 查询
示例的几篇文档都是关于机器学习的,这里尝试问一个和文档相关的全局问题 “What is machine learning?”
python -m graphrag.query --root ./ragtest --method global "What is machine learning?"
这里也有个坑,就是不要使用构建知识图谱时的模型 mistral,因为在查询过程中会使用如下的 system prompt(search.py):
search_messages = [
{"role": "system", "content": search_prompt},
{"role": "user", "content": query},
]
但是 mistral 对于 system prompt 的支持非常差,甚至视而不见,就导致输出结果不是 json 格式的,产生如下的报错:
这里我们在 settings.yaml 中将模型换成 llama3.1 就解决了。
回答结果如下:
Machine learning refers to a subset of artificial intelligence that involves training algorithms on data to enable them to make predictions or decisions without being explicitly programmed [Data: Entities (24)].
This approach allows machines to learn from experience and improve their performance over time, without the need for human intervention. Machine learning models can be trained on various types of data, including images, text, and numerical values, to perform tasks such as classification, regression, clustering, and more.
**Key Characteristics**
------------------------
Machine learning has several key characteristics that distinguish it from traditional programming:
* **Learning**: Machine learning algorithms learn from data and improve their performance over time.
* **Prediction**: Machine learning models can make predictions or decisions based on the learned patterns in the data.
* **Flexibility**: Machine learning models can be applied to a wide range of tasks, including classification, regression, clustering, and more.
**Explainable AI (XAI)**
-------------------------
The development of Explainable AI (XAI) within the Verdant Oasis community aims to make machine learning models more transparent and understandable [Data: Reports (40)]. XAI techniques provide insights into how machine learning models arrive at their predictions or decisions, enabling users to understand the reasoning behind the model's output.
**Implications**
----------------
Machine learning has far-reaching implications for various industries and applications, including:
* **Improved accuracy**: Machine learning models can learn from large datasets and improve their performance over time.
* **Increased efficiency**: Machine learning models can automate tasks and reduce the need for human intervention.
* **Enhanced decision-making**: Machine learning models can provide insights and recommendations to support informed decision-making.
Overall, machine learning is a powerful tool that has the potential to transform various aspects of our lives. By understanding its key characteristics and implications, we can harness its power to drive innovation and improvement in various domains.
第七步 用 VSCode Debug 项目
首先在 VSCode 中将该装的插件都装一装:
之后将项目目录下的 .vscode/launch.json 修改成如下:
{
"version": "0.2.0",
"configurations": [
{
"name": "graphrag index",
"type": "debugpy",
"request": "launch",
"module": "graphrag.index",
"console": "integratedTerminal",
"args": [
"--root", "./ragtest", "-v"
]
},
{
"name": "graphrag query",
"type": "debugpy",
"request": "launch",
"module": "graphrag.query",
"console": "integratedTerminal",
"args": [
"--root", "./ragtest", "--method", "global", "\"What is machine learning?\""
]
},
]
}
按照之前的步骤将 ragtest 目录初始化完成后,就可以开心地逐步调试了,下面的选项可以切换是调试 index 阶段,还是调试 query 阶段:
剩下的世界 以后再探索
本文限于篇幅和作者精力,就先介绍环境搭建步骤。
后续再写文章介绍整个项目的数据流,和其中对大模型工程的启发。敬请关注和期待。