GPT4All 本地关系抽取实战:不上传数据,把文档变成私有知识图谱
【免费下载链接】gpt4allGPT4All: Run Local LLMs on Any Device. Open-source and available for commercial use.项目地址: https://gitcode.com/GitHub_Trending/gp/gpt4all
你手里有一批产品手册、售后记录,里面藏着大量"谁和谁有什么关系",但数据不能出内网。这篇文章用 GPT4All 的本地大模型和嵌入(Embedding)能力,把文档拆成(主体, 关系, 客体)三元组,拼出一张私有知识图谱——全程离线,核心代码不超过 50 行。
为什么关系抽取要放在本地
云端 API 抽关系很方便,但两件事很难接受:
- 数据出境:文档原文要发出去,隐私和合规先过不了关;
- 成本随量涨:文档一多,token 费用持续发生。
GPT4All 是 Nomic AI 开源的本地 LLM 运行框架,可商用,核心思路是:
| 环节 | 由谁完成 | 作用 |
|---|---|---|
| 语义向量化 | Embed4All嵌入模型 | 把文本变成一组数字,方便比较含义远近、做实体归并 |
| 关系抽取 | GPT4All生成模型 | 读懂句子,吐出结构化三元组 |
| 文档入库 | 桌面端 LocalDocs | 把整个文件夹建成可检索、可引用的本地知识库 |
三个环节全在本地跑,文档一个字都不离开你的机器。
2 步装好环境并选对模型 🚀
第一步,克隆仓库并安装 Python 包:
git clone https://gitcode.com/GitHub_Trending/gp/gpt4all cd gpt4all/gpt4all-bindings/python pip install .如果不想从源码装,直接在 PyPI 执行
pip install gpt4all也可以。
第二步,按用途选模型。嵌入模型和生成模型是两回事:前者小、快、只产向量;后者大、慢、负责"读懂并回答"。
| 用途 | 模型名 | 体积 | 特点 |
|---|---|---|---|
| 嵌入 | all-MiniLM-L6-v2(默认) | 44 MiB | 384 维,512 词上下文,最省心 |
| 嵌入 | nomic-embed-text-v1.5 | 262 MiB | 维度 64~768 可调,2048 词上下文 |
| 生成 | Meta-Llama-3.1-8B-Instruct-128k-Q4_0.gguf | 约 5 GB | 8B 参数,长上下文,需 8 GB 以上内存 |
from gpt4all import GPT4All, Embed4All embedder = Embed4All() # 首次运行自动下载 all-MiniLM-L6-v2 model = GPT4All("Meta-Llama-3.1-8B-Instruct-128k-Q4_0.gguf", n_ctx=4096)n_ctx=4096把上下文窗口从默认 2048 提到 4096,方便一次塞进完整段落。模型首次加载会自动下载到~/.cache/gpt4all/,之后离线可用。
一段提示词拿到实体三元组
抽取质量一半靠模型,一半靠提示词约束输出格式。把"只输出三元组"写进系统消息,模型就不会加戏:
SYSTEM = "你是关系抽取助手,只输出(主体, 关系, 客体)三元组,每行一条,不加任何解释。" text = "智能温控器 X300 支持 Wi-Fi 与蓝牙双模连接,工作温度 0~40°C,需 4.5V 供电。" with model.chat_session(system_message=SYSTEM): print(model.generate(f"抽取以下文本的实体关系:{text}", max_tokens=150))典型输出:
(X300, 连接方式, Wi-Fi) (X300, 连接方式, 蓝牙) (X300, 工作温度, 0~40°C) (X300, 供电, 4.5V)两个小建议:
- 温度调低:抽取是"要准"的任务,把
temp调到 0.2 左右,输出更稳定; - 一条文档拆短句:一次给 3~5 句话效果最好,整篇塞进去容易漏。
本地嵌入:把文字变成可比较的向量 🔍
三元组里的实体经常"叫法不统一"——"X300""该温控器""温控器 X300"其实指同一个东西。嵌入就是干这个的:把文本映射成向量,余弦相似度越接近 1,含义越近。
vecs = embedder.embed(["X300 智能温控器", "该温控器", "X300 无人机"]) def cosine(a, b): dot = sum(x * y for x, y in zip(a, b)) na = sum(x * x for x in a) ** 0.5 nb = sum(y * y for y in b) ** 0.5 return dot / (na * nb) print(f"{cosine(vecs[0], vecs[1]):.4f}") # 同指物,得分接近 print(f"{cosine(vecs[0], vecs[2]):.4f}") # 跨领域,得分明显更低拿到相似度后设个阈值(比如 0.75),把超阈值的实体名归并为同一节点,三元组里的主体/客体就统一了,图谱不会出现一堆指向同一产品的"分身"。
想省内存可以把向量降维:embedder.embed(text, dimensionality=128),注意仅 Matryoshka 模型(如 Nomic Embed v1.5)支持,默认的 all-MiniLM-L6-v2 固定 384 维。
把整个文档库灌进来,规模化抽取 📚
单条句子抽完了,下一步是处理整个文件夹。GPT4All 桌面端的LocalDocs就是干这个的:选一个文件夹建集合(Collection),它会在本地把文件切成文本片段并逐个生成嵌入向量;聊天时开启 LocalDocs,模型会先检索语义最接近的片段作为上下文,回答下方还能点开Sources查看引用了哪些文件。
这套"检索片段 → 注入提示 → 生成回答"的流程就是本地 RAG,关系抽取可以直接复用它:把提示词从"回答问题"换成"抽取三元组"即可。
纯 Python 侧的批处理逻辑也很直白——分块、循环、落盘:
chunks = load_chunks("manuals/") # 你的分块函数,每块 200~500 字 triples = [] for chunk in chunks: with model.chat_session(system_message=SYSTEM): triples.append(model.generate( f"抽取以下文本的实体关系:{chunk}", max_tokens=150)) with open("triples.txt", "w", encoding="utf-8") as f: f.write("\n".join(triples))抽出的三元组可以先存成 JSONL,再导入 Neo4j 或任何图数据库,用可视化工具渲染成图谱。
常见问题:离线、内存和上下文 ❓
能完全离线吗?能。模型只在首次加载时下载一次,缓存在本地,之后断网也能正常推理和嵌入。
内存不够跑 8B 怎么办?Q4_0 量化后的 8B 模型需要 8 GB 以上内存。只有 4 GB 的话换Phi-3-mini-4k-instruct.Q4_0.gguf(约 2.2 GB),抽取短句关系足够用;有独显还可以加device="gpu"加速。
上下文窗口怎么定?默认n_ctx=2048,128k 版本可按需调大,但窗口越大内存占用越高,"够用即可"。
下一步可以做什么
- 先用小模型在你自己的文档上跑通三元组抽取,把阈值和提示词调顺;
- 把三元组入库后,按"实体 → 关系"聚合,检查孤点(只出现一次的实体),往往是切块或提示词的问题;
- 深入阅读官方文档:Python API 说明 gpt4all-bindings/python/docs/gpt4all_python/home.md,LocalDocs 工作原理 gpt4all-bindings/python/docs/gpt4all_desktop/localdocs.md。
【免费下载链接】gpt4allGPT4All: Run Local LLMs on Any Device. Open-source and available for commercial use.项目地址: https://gitcode.com/GitHub_Trending/gp/gpt4all
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考