Qwen系列模型+GraphRAG/LightRAG/Kotaemon从0开始构建中医方剂大模型知识图谱问答

简介: 本文详细记录了作者在短时间内尝试构建中医药知识图谱的过程,涵盖了GraphRAG、LightRAG和Kotaemon三种图RAG架构的对比与应用。通过实际操作,作者不仅展示了如何利用这些工具构建知识图谱,还指出了每种工具的优势和局限性。尽管初步构建的知识图谱在数据处理、实体识别和关系抽取等方面存在不足,但为后续的优化和改进提供了宝贵的经验和方向。此外,文章强调了知识图谱构建不仅仅是技术问题,还需要深入整合领域知识和满足用户需求,体现了跨学科合作的重要性。

引言

本来最近知识图谱就已经很火爆了,社区也有不少小伙伴都写了很多文章,都让周周从中受益匪浅。这些文章不仅详细介绍了知识图谱的基本概念和技术原理,还分享了许多实战经验和技巧,为初学者和研究者提供了宝贵的参考资料,特别是在构建知识图谱的过程中,如何处理大规模数据、优化模型性能以及提升知识抽取的准确性等方面的内容,更是让周周受益良多。

刚好最近周周面临工作年龄生活等诸多压力,决定转行学中医(《25岁大龄程序猿转行学中医》)。作为一个中医初学者,面对浩如烟海的药材、方剂和理论,常常感到无所适从。中医药学博大精深,不仅包含了大量的药理知识,还有独特的诊断方法和治疗理念,如何快速、系统地学习和理解这些知识,是一个巨大的挑战。

61969b583dacb614502f5c338bdcd64.jpg

这时,周周想到了可以利用知识图谱技术来系统化和结构化中医药知识。通过构建一个中医药知识图谱,不仅可以帮助自己更好地理解和记忆复杂的中医药知识,还可以为其他中医爱好者和专业人士提供一个强大的工具。

理论学习

本着从0开始的精神,为了保证中医药知识图谱的准确性和可用性,我专门学习了中国医学科学院/北京协和医学院医学信息研究所医学知识图谱构建与应用,虽然这个分享不仅仅针对于中医,但是确实也为我提供了一定的基础和较为系统的知识框架。(下面为笔记内容)

从宏观层面来说,知识图谱构建与应用主要分为两大块内容:一种是医学领域知识图谱构建与应用,一种是医学科研机构图谱构建与应用

image.png

在医学知识图谱构建时,整体的流程和构建普通知识图谱是一样的,主要包括:知识建模、知识抽取、知识融合、图谱发布及应用

知识建模

在进行知识建模中,会遵循从通用疾病——>专病的原则。

在通用疾病图谱构建时,以病种为出发点,然后再结合相关的目标和任务场景,向如临床表现、症状体征、检查检验等其他实体进行辐射。在整个模型建模过程当中,为了考虑到和机构或者单位之间的互通(通用性),无论是在关系的界定上,还是属性或者标签的命名上面,都是尽可能参照现有的权威的知识体系来做的。在这个基础之上没有的,才会根据实际的需要,来做个性化的定制和扩展。

image.png

在病种的定义上,也尽可能的是多维化的。因为我们对一个疾病的认识,不管是我们临床上的认识,还是说我们这实际上在整个应用过当中,我们的角度不一样,对这个病种的组织的整体的框架和依据不一样。当我们了解一个疾病诊断的时候,我们可能需要从这个病因部位病理临床表现等等不同的角度去认识它。

image.png

抽取、融合与对齐

在整个构建过程当中,重点围绕的这个技术点就是在知识的抽取和融合和对齐还有知识的更新这个方面。刚刚讲到就是说我们在整个建模和这个过程当中,是对这个现有知识体系的尽可能是一个复用。第二个就是说实际上在整个做概念知识的抽取和构建过程当中,也会尽可能的引用这个或者参照现有的规范体系。这里面可能就是涉及到就是说当我们把现有的这个知识体系拿过来以后,参检过来以后,我们怎么对它做更好的一个融合

image.png

最基本的最核心的技术就是要把词表来源的概念做统一的规定。规定完了以后,推荐一个比较认可的,或者说在某个场景下认可的一个优选词来统领它。在这个过程当中,除了我们传统的通过各种相似度判断、通过各种学习的方法判断,最主要的是从不同术语类型的传导规则来进行控制,还有对这个不同词表间概念和力度的控制,做了一些研究和实践,比如说不同的词表,它的概念不一样,它的力度不一样,它的术语类型不一样,所以在这个整体里面所起到的关键作用也是不一样。

image.png

除了规范的知识源抽取以外,还面向非结构化文本抽取。一个是从中文科技文献里面(比如期刊论文、学位论文)抽取和识别新的未登录词,或者抽取领域开放关系,抽取完成后再来对我们现有的知识重新组织,对知识图谱或者体系进行扩充。

image.png

第三个抽取的文本主要是电子病历这一块。大家在做应用的时候,很大的一个痛点就是会发现我们图谱里面的这些词是不够用的,看着量也挺多的,概念数也挺多的,但是它的同义词可能是不足以覆盖我们这个真实的数据的。所以说这里就尝试着从真实的电子病历里面,去抽取我们想要的一些不同类别的实体,进而来丰富这些术语,或者说不同类型的概念覆盖范围。

image.png

第四个抽取的是药品说明书。除了刚刚说的疾病以外,药物实际上也是我们构建图谱的一个维度,是第二中心点。我们会从这个药物出发,然后去构建这样的一个体系,识别它跟不同的疾病之间的适应症、禁忌症的关系,药物和药物之间的配伍和禁忌的关系,药物和人群之间的禁用和慎用的一些关系,这些实际上都是要从比较高质量的药品说明书里面来获得的。

image.png

从说明书里面抽取疾病症状、检查检验药物、手术这一块,整体来看,光靠模型还不太够,还是需要将模型、规则、特征结合起来。

当这些知识抽完了以后,我们其实最关键的还是要把它怎么放到我们的图谱里面去。我们到底是把它作为一个新的概念,或者说新的一个实例放进去,还是说我们要把它融入到我们现有的某个概念里面去。这个实际上是我们要做的一个所谓的规范性控制的工作。

在这个过程当中,其实我们做了不同类别的,像刚刚说的这个解剖、疾病、药物等。我们会发现这个不同类型的实体,它是对不同技术的模型的敏感度实际上是不一样的。

在这里面主要是总结了一套不同的术语类型,或者说它的一个知识类型。最基本的最后我们会回归到这个相似度的计算模型里面去,当我们做跟现有规定概念匹配的时候,我们遵循的路径实际上是跟我们整个知识图谱的架构是关联起来的。

image.png

在所有工作当中,其实有两类术语一直在干扰着我们的准确率,一个是歧义术语,另一个是缩略语。通过构建一个规范文档,然后来对这些歧义术语和缩略语进行语义控制。

比如当看到Airways时,能够让计算机知道这到底是医学领域的呼吸气道的概念,还是说是这个理学里面的航空航道的概念。

image.png
image.png

除了专家的审核、校验以外,在质量控制方面也采取了一些措施,包括从这个数据的抽取,到这个数据的分类,抽取完了以后,整个对它进行统一规定,还有我们这个统一关系识别出来的关系,然后怎么来对它进行异常的一些检测等。

这里面其实还有很多关系:不对称,闭合、循环、置反等等。还有这个概念,这个力度上,就是大家会经常看到有的为什么有的字典里面或者图谱里面那个那个概念的这个同义词那么多哈。那么有有时有时候可能就是他真的出错了。但是有时候它并不是真的出错,而是它的一个组织的需要。比如说这个match里面,它从它的主题的角度来说,他就是把这个运动和有氧运动和等级运动归在一块了。

image.png

成果示例

image.png
image.png

感慨一下,构建一个完整的中医药知识图谱确实是庞大而复杂的工程,其中涉及多个学科领域的知识和技术,大早上的给我头都看麻了,细想一下,我一个人肯定是做不到特别完善的,所以重点还是在于技术上的实现,至于其中的数据集我还是决定采用别人专业从业者所提供的

GraphRAG/LightRAG/Kotaemon

要说到RAG,其实大家都不陌生,它本质是结合了信息检索和生成模型,通常是先使用检索模块从一个大型文档集合中找到相关信息,然后由生成模块生成自然语言结果,生成过程会参考检索到的文档。

image.png

随着最近出了比较火的GraphRAG,相继微软也开源了他们的Graph RAG方案,上面的RAG就成了所谓的传统RAG

传统RAG虽然表现优异,但其局限性也不容忽视:

  • 数据结构扁平化 : 传统 RAG 系统往往依赖扁平化的数据结构,难以捕捉信息之间的复杂关系。这种缺陷导致生成的答案片段化,缺乏上下文的一致性。

  • 有限的上下文意识 : 系统在处理需要综合多个数据点的复杂问题时表现不佳,生成的答案缺乏对数据间相互关联的全面理解。

而GraphRAG作为新兴RAG在传统RAG架构中引入了图结构,使其能够更好地表示信息之间的关系。通过图模型,GraphRAG可以捕捉和分析多个文档之间的复杂连接和依赖。

LightRAG其实也是属于GraphRAG宏观含义下的一类框架,对比微软本身提出的GraphRAG,它通过优化模型架构和算法设计,在保持高效信息检索和对话生成性能的同时,显著降低计算成本和资源消耗。它采用了一系列创新技术,比如稀疏注意力机制、动态图更新策略、双层检索框架等,使得模型能够在较小规模的数据集上快速训练,并且在推理阶段也能实现高效的响应速度。

本节重点是旨在比较GraphRAG,LightRAG以及最新的Kotaemon这三个框架的优劣和使用特性。

GraphRAG

原本 GraphRAG 只支持 OpenAI 的闭源大模型,导致部署后使用范围大大受限,并且调用API价格昂贵,但有大佬修改了源码并直接制作了WebUI界面,所以我们这里直接去使用修改后的GraphRAG。

Github地址:https://github.com/severian42/GraphRAG-Local-UI

安装步骤

1.创建并激活新的conda环境:

conda create -n graphrag-local -y
conda activate graphrag-local

image.png

2.安装所需的软件包:

首先从这个repo中安装GraphRAG目录(有微软repo中没有的更改)

pip install -e ./graphrag

然后安装其余的依赖项:

pip install -r requirements.txt

image.png

3.启动API服务器:

python api.py --host 0.0.0.0 --port 8012 --reload

image.png

4.使用Ollama进行嵌入,要启动嵌入代理:

python embedding_proxy.py --port 11435 --host http://localhost:11434

image.png

5.启动索引:

gradio index_app.py

image.png

6.启动主要交互式UI:

gradio app.py   或者

python app.py

image.png

7.访问用户界面:

image.png

image.png

测试使用

到了这一步,我们已经可以成功看到可视化界面了,下面进入到http://127.0.0.1:7861/ 中继续

大模型选择本地Ollama部署的Qwen-2.5-7b

image.png

嵌入模型也可以选择同样的

image.png

选择完成后保存配置

image.png

保存后下面的配置就会变成这个样子

image.png

剩下部分保持默认不变

image.png

但这一步骤实际是根据文件大小来决定时间,初期测试可以用个小文件,执行期间可以看日志,执行完成会有如下成功标识: All workflows completed successfully. ;如果执行报错再调整这部分。

点击Run Indexing 构建索引测试,出现如下字样表示构建开始

image.png

然后可以点击Data Management,进入到上传位置,点击上传按钮

image.png

先选择一个小文件进行尝试

image.png

上传之后再点击Upload File,此时可以看到上传状态

image.png

我们点击Refresh File List,选择刚刚上传的文件(后面为方便确认,将文件名修改为中文了)

image.png

可以看到能够读取到我们的文件内容:

image.png

此时下方一定要点击保存,否则可能出现报错:

image.png

正式使用

再来到http://127.0.0.1:7860/ 中 ,正式开始构建一个知识图谱

进到如下位置,刷新后选择本地大模型和嵌入模型

image.png

选择完之后点击 Update LLM Settings

image.png

回到Data Management中,依旧按照之前的方式上传文档

image.png

选择文档后,点击保存修改

image.png

同样,我们也可以制作索引,操作方式与测试时一致

image.png

最终构建完成时提示如下:create final documents All workflows completed successfully.

image.png

此时我们先可以进行提问尝试,选择本地,实际上这里实现的就是一个简单的RAG

image.png

切换到 Indexing Outputs/Visuals 下,可以将刚才的文件进行知识图谱可视化

image.png

选择刚才输出的文件

image.png

对应选择到该目录下的 summarized_graph.graphml文件

image.png
image.png

最终可以在可视化界面看到构建出来的立体知识图谱

image.png

说实话,整个部署过程比较艰难,而且结果也一言难尽,果然一股脑把数据灌进去还是会出问题的。。。

LightRAG

LightRAG是个精炼的RAG框架,专门用于通过检索关键知识片段来构建响应,并且整合了知识图谱和嵌入技术。与那些将文档简单拆分成独立片段的传统RAG系统不同,LightRAG进一步深化了这一过程——创建了实体与实体之间的关系对,将文本中的概念紧密联系起来。与微软的GraphRAG相比,两者有相似之处,但LightRAG在速度和成本上更具优势,并且支持对图谱进行增量更新,无需每次都重新生成整个图谱。

传统的RAG系统在处理文档时,会将其分割成多个独立的块进行检索,但这种方法往往忽视了这些块之间的上下文联系。当问题的解答需要跨越多个块时,就难以给出准确的回答。LightRAG通过创建知识图谱巧妙地解决了这一难题,它能够清晰地描绘出数据中实体间的相互关系,从而在处理复杂问题时提供了更为精确的答案。

image.png
LightRAG的工作流程主要分为两大环节:索引和检索

在LightRAG中,数据索引涉及以下几个步骤:

  • 分块:将文档切割成小块,以便更精细地处理。

  • 实体识别:在每个小块中,LLM识别出实体,比如人名、地点或概念。

  • 关系提取:确定这些实体间的关系,形成实体-关系的键值对。

  • 知识图谱构建:将这些键值对整合成图结构,并去除重复节点和冗余关系,以优化图谱。

  • 嵌入存储:将描述和关系转化为向量,存储在向量数据库中,如LightRAG默认的Nano Vector数据库。

LightRAG采用双层检索策略,结合本地和全局查询:

  • 低层检索:聚焦于单个实体相关的节点,以回答具体问题,提取精确细节,例如电动汽车的具体统计数据或法规。

  • 高层检索:识别整个图谱中的总体主题和连接,关注更广泛的议题,如环境趋势或城市交通的发展前景。

这种双层检索机制确保了系统能够提供既全面又深入的答案,兼顾事实和背后的深层上下文。

Github地址:https://github.com/HKUDS/LightRAG

安装步骤

首先安装一下LightRAG库,官方建议从源码安装

git clone https://github.com/HKUDS/LightRAG.git
cd LightRAG
pip install -e .

image.png
image.png

由于所有的GraphRAG都依赖大模型进行文本的图谱构建,是相当耗费资源的,所以这里我选择使用Ollama部署本地的开源大模型

模型选用的是qwen2.5的7b

接着我们来配置LightRAG,这里我没有使用大模型的Embedding,而是选择了BAAI/bge-large-zh-v1.5,效果会更好

但这里就需要自定义LightRAG提供的EmbeddingFunc实例,主要是设置embedding_dim和max_token_size,以及提供具体的embedding获取函数(得是batch粒度的接口)

rom llama_index.embeddings.huggingface import HuggingFaceEmbedding
from lightrag.utils import EmbeddingFunc

embedding_model = HuggingFaceEmbedding(model_name="BAAI/bge-large-zh-v1.5")
embedding_func = EmbeddingFunc(
    embedding_dim=1024,
    max_token_size=8192,
    func=lambda texts: embedding_model.aget_text_embedding_batch(texts),
)

然后就可以初始化LightRAG了

import nest_asyncio
from lightrag import LightRAG, QueryParam
from lightrag.llm import ollama_model_complete
from glob import glob

nest_asyncio.apply()
rag = LightRAG(
    working_dir="./interview_lightrag",
    llm_model_func=ollama_model_complete,
    llm_model_name="qwen2.5:7b",
    embedding_func=embedding_func,
)

接下来只需要向LightRAG中插入数据,处理完我的全部文件,耗时2h,还是很长的

for file in glob("C:/Desktop/fangji.txt", recursive=True):
    with open(file, "r", encoding="utf-8") as f:
        rag.insert(f.read())

image.png

结果一尝试问答,心态就炸了,完全在胡言乱语。。。

学习了一下别人大佬的思路,确实还是存在比较多的问题:

  1. LightRAG的prompt模板是全英文的,所以对于中文的数据和大模型,效果肯定是有影响的

  2. 使用的是开源的Qwen2.5的7b模型,参数量较少,抽取和图谱构建效果不够好

  3. 文档数据都是专业性很强的中医数据,所以embedding的效果和信息抽取的难度肯定也更大。

简单看看构建图谱的可视化效果(这段在Jupyter Notebook中运行可能不会成功,需要放到脚本中运行得到一个html文件然后用浏览器打开)

import networkx as nx
from pyvis.network import Network

# Load the GraphML file
G = nx.read_graphml("./interview_lightrag/graph_chunk_entity_relation.graphml")

# Create a Pyvis network
net = Network(notebook=True)

# Convert NetworkX graph to Pyvis network
net.from_nx(G)

# Save and display the network
net.show("knowledge_graph.html")

图谱大概长这样:

image.png

可以看到图谱非常稀疏,抽取到的三元组质量也差强人意,所以LightRAG的回答效果不好也在情理之中

不过这也与调用的模型能力有关,所以并不能说LightRAG这个工具不好

Kotaemon

这里重点想介绍的还是Kotaemon,之前在收集资料时没有看到这个,直到在B站碰巧刷到了一个大佬做的Kotaemon与LightRAG的对比,在学习之后才发现这个工具的强大

首先,Kotaemon与LightRAG的最大区别就是Kotaemon是一个比较稳定的企业级RAG框架

对于大部分使用RAG框架的用户来说,他们的需求要么就是搭建个人的知识库,要么就是为企业搭建知识库。对于需要搭建个人知识库或者企业知识库的用户来说,我们所选择的框架首先就是稳定,其次就是简单易用。

开源的LightRAG它在稳定性方面并不是很好。因为这个项目的代码不够健壮,而且对模型的支持度不好,并且它不支持PDF等其他格式的文件,只支持TXT文件。还有就是在这个项目的源代码中,像OpenAI等模型,它采用了硬编码。他将GPT4o GPT4o mini还有claude的模型硬编码到了代码里,想自定义模型的话,我们只能自己修改项目的源代码。对于不懂编程的用户来说,还是具有一定挑战性的。

image.png

所以,不论是对企业用户来说,还是个人用户来说,都不太推荐这个项目。因为真正符合企业标准的RAG项目,能够让用户快速上手,而且能够支持多种文件格式

而这里提到的:Kotaemon自带有UI界面,非常适合没有编程经验的用户快速构建自己的知识库

Kotaemon部署

Kotaemon是一个开源的项目,专注于构建和使用基于检索增强生成(RAG)的管道,主要用于文档的问答任务。它提供了一个简洁的用户界面,允许用户通过混合检索(全文和向量检索相结合)在文档中进行高效查询,确保返回结果的高相关性。

Kotaemon 支持多个大语言模型(LLMs),包括来自 OpenAl和 Azure 等提供商的 API,以及使用本地模型(如llama-cpp-python)的能力。其主要功能包括支持多用户登录、管理私密和公共文档集合,并且能够组织和管理各种 LLM和嵌入模型。

对于开发者,Kotaemon 提供了一个灵活的框架,能够轻松构建自定义的 RAG 管道,且集成了基于 Gradio 的交互式 UI,支持进一步的自定义。此外,该系统支持复杂推理功能,如问题分解、多跳问题推理等,并可通过 Docker 容器部署,简化安装和扩展。

Github:https://github.com/Cinnamon/kotaemon/releases/tag/v0.9.2

image.png

下载完后解压进入scripts,根据系统安装,如windows系统双击run_windows.bat,linux系统bash run_linux.sh

image.png

执行后如下所示,安装过程大概15分钟,安装过程如果提示比如什么Failed to download 7-Zip. Aborting... 就直接采用源码安装来进行:

image.png

安装后,程序要求启动ketem的UI,点击”继续”即可

image.png

如果启动成功,会自动在浏览器中打开,默认账户名和密码是admin/admin

image.png

除了这种方式之外,还可以通过docker和本地源码安装

docker run \                      ##docker安装
-e GRADIO_SERVER_NAME=0.0.0.0 \
-e GRADIO_SERVER_PORT=7860 \
-p 7860:7860 -it --rm \
--platform linux/arm64 \
ghcr.io/cinnamon/kotaemon:main-lite

image.png

# Create a virtual environment              ##本地源码安装
python3.10 -m venv kotaemon_env

# Activate the virtual environment
# On Unix or MacOS, use:
source kotaemon_env/bin/activate
# On Windows, use:
# kotaemon_env\Scripts\activate

# Clone the repository
git clone https://github.com/Cinnamon/kotaemon
cd kotaemon

# Install kotaemon and its dependencies
pip install -e "libs/kotaemon[all]"
pip install -e "libs/ktem"

# When you're done, you can deactivate the virtual environment
# deactivate

当源码安装之后,进入文件夹中,将env.example复制为env文件,方便后续对其进行修改

image.png

可以看到这里除了支持ollama本地模型之外,还支持OpenAI等API

image.png
image.png

我们进入默认打开的界面如下:

image.png

这里我们采用两种方式,第一种还是使用本地的Qwen2.5-7b,第二种我是想尝试一下最新的qwq-32b-preview,据说是很强的推理模型,那么在知识图谱的生成上肯定会有优势的

如果采用本地的话,需要进入如下界面,修改本地模型调用为默认,并且把模型名称修改为qwen2.5:7b

image.png

保存后会有如下提示

image.png

同时这里也可以先对模型连通性进行测试,测试成功会提示如下:

image.png

同样,我们修改嵌入模型

image.png

测试嵌入模型如下:

image.png

回到文件界面,我们上传之前准备好的中医方剂文档,并开始制作索引:

image.png

制作完成后,回到主界面,尝试本地RAG,成功后结果如下:

image.png

请各位量力而行,还是很吃显卡配置的

image.png

同样,我们来制作知识图谱,按照如下步骤所示,上传txt文本:

image.png

但是会发现,抽取知识图谱时报错

image.png

经过排查,发现这个项目其实算是个半成品,不知道谁在吹说什么稳定和可以直接用于生产,光是github上提的bug就一百多个,而且此次部署中出现的问题甚至找不到合适的解决方法,这就非常麻烦了,例如下面这个问题,就至少有20个人碰到了但一直不知如何解决

6e2d8d0a0dd77e1f9004a93dbc23c32.png

考虑到之前是采用使用者模式一键部署的,周周这里决定卸载后重新采用源码安装一次,看能不能绕开这个bug

# 创建虚拟环境
conda create -n kotaemon python=3.10
conda activate kotaemon



# 下载源码
git clone https://github.com/Cinnamon/kotaemon
cd kotaemon



# 安装依赖
pip install -e "libs/kotaemon[all]"
pip install -e "libs/ktem"


# 更新环境变量文件.env,如API key
# (可选) 如果想浏览器内部展示PDF,可以下载PDF_JS viewer,解压到libs/ktem/ktem/assets/prebuilt目录


# 开启web服务,并使用admin/admin登录
python app.py

安装完成后进到.env文件下,修改.env文件中的行如下:

USE_CUSTOMIZED_GRAPHRAG_SETTING=true

image.png

然后调整 settings.yaml.example里面如下几个设置为true

embed_graph:
  enabled: true # if true, will generate node2vec embeddings for nodes
  # num_walks: 10
  # walk_length: 40
  # window_size: 2
  # iterations: 3
  # random_seed: 597832

umap:
  enabled: true # if true, will generate UMAP embeddings for nodes

snapshots:
  graphml: true
  raw_entities: true
  top_level_nodes: true

image.png

在执行安装依赖包时,可能会出现报错的情况:

 Could not find a version that satisfies the requirement llama-hub<0.1.0,>=0.0.79

这时需要进入到如下文件中,删除其中的llama-hub后面的版本,再重新下载依赖

image.png
image.png

总之后面又碰到了很多奇奇怪怪的问题,最后采用docker安装才成功装好了

效果差不多也就如下图所示,这里使用的是官方默认提供的文档索引:

image.png

关于Kotaemon体验的感受就是,UI界面很友好,使用十分简易,但是部署过程中会碰到各种奇奇怪怪的问题(即使按照官方给出的操作文档都会出现问题),生态不够好,问题数量太多了,作者在github上也没时间全部都一一回答,长远来看会是一个比较优秀的开源项目,但是目前还有很多的不足。

总结

通过这几天的研究,总结出坑点如下:

  • 部署最好都使用源码部署,不要去找别人的二开界面

  • 如果纯靠大模型进行抽取,不要使用什么7B,14B的本地模型,至少得使用70B以上的模型,要不然知识抽取做的一团糟

  • 目前来看GraphRAG和LightRAG各有优势(Kotaemon实际调用的就是微软的GraphRAG),不存在一边完全优于另一边的情况

image.png
该图片引用自https://github.com/NanGePlus/LightRAGTest

在仅考虑时间成本和金钱成本的前提下,采用LightRAG会是很好的选择,而且经过测试发现本地模型(7b、14b)效果太差,所以要么是本地设备很好可以跑70b以上的大模型,要么就必须使用第三方API,时间成本和金钱成本是极其关键的!

结果综合对比

  • Local检索:本地搜索方法将知识图谱中的结构化数据与输入文档中的非结构化数据结合起来,在查询时用相关实体信息增强 LLM 上下文

  • Global检索:根据LLM生成的知识图谱结构能知道整个数据集的结构(以及主题)这样就可以将私有数据集组织成有意义的语义集群,并预先加以总结。LLM在响应用户查询时会使用这些聚类来总结这些主题

  • Hybride/Drift检索结果:DRIFT 搜索通过整合社区信息,使本地搜索的起点更为宽泛,能够检索更多类型的事实,从而提升查询的详细性。DRIFT 在 GraphRAG 的查询引擎基础上进一步扩展,为本地搜索提供了更精细的分层查询方式,使其能够处理与预定义模板不完全匹配的复杂查询)

采用这三种方式制作出来的结果综合对比下,从个人感官上而言,Local检索和Global检索下,GraphRAG和LightRAG效果基本一致;在Drift检索下,GraphRAG远优于LightRAG

image.png

基于Qwen-QwQ-32B+LightRAG自动构建知识图谱

鉴于上面效果并不是很好,所以下面我还是采用API的方式,刚好阿里云推出了最新的Qwen-QwQ-32B,并赠送了一些免费额度,所以准备使用该模型

具体的部署方式在上面已经给出了,此处也不过多赘述

回到LightRAG文件夹下,我们选择 lightrag_openai_compatible_demo.py

image.png

因为是单位的电脑,所以我也懒得装pycharm了,直接记事本编辑就OK了

比较关键的几个位置修改一下

async def llm_model_func(
    prompt, system_prompt=None, history_messages=[], **kwargs
) -> str:
    return await openai_complete_if_cache(
        "模型名称",
        prompt,
        system_prompt=system_prompt,
        history_messages=history_messages,
        api_key="模型API-key",
        base_url="模型地址",
        **kwargs,
    )
async def embedding_func(texts: list[str]) -> np.ndarray:
    return await openai_embedding(
        texts,
        model="模型名称",
        api_key="模型API-key",
        base_url="模型地址",
    )
   rag = LightRAG(
            working_dir=WORKING_DIR,
            llm_model_func=llm_model_func,
            embedding_func=EmbeddingFunc(
                embedding_dim=embedding_dimension,
                max_token_size=8192,
                func=embedding_func,
            ),
        )

        with open("文件地址", "r", encoding="utf-8") as f:
            await rag.ainsert(f.read())

这三个位置修改完之后直接本地执行

python lightrag_openai_compatible_demo.py

我之前用的数据集是3.7M(124万字) ,得跑300个小时(后来发现跑着跑着时间会比预估短很多),这里采用的测试数据集是(10万字)慢慢等着跑完就可以了,基于Qwen-QwQ-32B的话预估时间至少也是2个小时左右

关于Qwen-QwQ-32B的API的话可以在百炼平台获取,具体可以参看我之前的文章

image.png

在模型额度这里可以看到自己还有100万的免费token,所以也推荐小伙伴使用该模型尝试

image.png

但是这里还有一个坑点需要提醒一下,在embedding模型选择上,如果直接调用阿里的会报错,因为会默认在路径后面加个embedding,导致404访问错误,而百炼里面也没有直接提供baseurl版的向量模型调用,所以我这里的embedding选择的是siliconflow里面的

image.png

siliconflow里面提供了比较多免费的embedding模型,我选择的是BAAI/bge-m3

image.png

所以,最终的lightrag_openai_compatible_demo.py如下:


async def llm_model_func(
    prompt, system_prompt=None, history_messages=[], **kwargs
) -> str:
    return await openai_complete_if_cache(
        "qwq-32b-preview",
        prompt,
        system_prompt=system_prompt,
        history_messages=history_messages,
        api_key="API-Key",
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
        **kwargs,
    )


async def embedding_func(texts: list[str]) -> np.ndarray:
    return await openai_embedding(
        texts,
        model="BAAI/bge-m3",
        api_key="API-Key",
        base_url="https://api.siliconflow.cn/v1",
    )

image.png

同时,这里又会碰到坑,就是siliconflow里面会给你限速

image.png

跑一会儿就报超时了

image.png

这时重新再执行一次脚本即可,会保留之前提取的实体和chunks

image.png

跑完后最终效果如下所示:

image.png

比之前好了一些,但是效果依然没有达到最理想的状态

对比小说和故事类的话,中医方剂的提取在效果上差了很多,同时,由于经费的限制,不管是大模型还是嵌入模型的选择都是用的免费的,所以影响了最终效果

image.png

除去这种完全由大模型接管的方式外,还有一种方式就是手动使用大模型抽取关系,再结合neo4j数据库进行知识图谱构建

基于大模型的关系抽取和neo4j知识图谱构建

利用大模型抽取关系需要用到一套特定的prompt,这里周周给出了自己使用的,以供大家参考

假设文本内容如下:

阿胶地黄汤    阿胶地黄汤    【来源】《太平圣惠方》卷三十七。    【组成】生干地黄120克阿胶60克(捣碎,炒令黄燥)蒲黄60克    【用法】上药捣筛为散。每服9克,以水250毫升,入竹茹1鸡子大。煎至125毫升,去滓,食后温服。    【主治】热伤肺脏,唾血不止。    按:本方在原书中无方名,现据《普济方》卷一九○补。
阿胶黄连汤    阿胶黄连汤    【来源】《重订通俗伤寒论》。    【组成】陈阿胶4.5(烊冲)生白芍6克小川连1.8(蜜炙)鲜生地18克青子芩3克鸡子黄1枚(先煎代水)    【用法】水煎服。    【主治】伤寒邪传少阴,水为火烁,心烦不寐,肌肤枯燥,神气衰弱,咽干溺短,舌红尖绛,脉左细数,按之搏指,右脉反大而虚软者。
阿胶黄芩汤    阿胶黄芩汤    【来源】《重订通俗伤寒论》。    【组成】陈阿胶青子芩各9克甜杏仁生桑皮各6克生白芍3克生甘草2.4克鲜车前草甘蔗梢各15克    【用法】先用生糯米30克,开水泡取汁出,代水煎药。    【主治】秋燥。肺燥肠热,上则喉痒干咳,咳甚则痰粘带血,血色鲜红,胸胁串痰;下则腹热如焚,大便水泄如注,肛门热痛,甚或腹痛泄泻,泻必艰涩难行,似痢非痢,肠中切痛,有似鞭梗,按之痛甚,舌苔干燥起刺,兼有裂纹。
阿胶鸡子黄汤    阿胶鸡子黄汤    【来源】《重订通俗伤寒论》。    【组成】陈阿胶6克(烊冲)生白芍9克石决明15克()双钩藤6克大生地12克清炙草1.8克生牡蛎12克()络石藤9克茯神木12克鸡子黄2枚(先煎代水)    【用法】水煎服。    【功用】滋阴熄风。    【主治】伤寒邪传少阴,水亏火亢,液涸动风,筋脉拘挛,手足瘈疭者。
阿胶济阴汤    阿胶济阴汤    【来源】《胎产秘书》卷上。    【组成】阿胶白术各3克白芍当归川芎各3克砂仁(带壳)1.5克条芩蕲艾各4.5克香附2.4克炙甘草1.5克粘米1捏    【用法】用水500毫升,煎至250毫升,温服。    【主治】妊娠伤胎,致令子宫虚滑,经血淋漓者。
阿胶梅连丸    阿胶梅连丸    【来源】《宜明论方》卷十。    【组成】金井阿胶(净草灰炒透明白,别研,不细者再炒,研细)乌梅肉(去核,炒)黄柏(锉,炒)黄连当归()赤芍药干姜()赤茯苓各15克    【用法】上药研末,入阿胶研匀,水丸,如梧桐子大,小儿丸如绿豆大。每次10丸,空腹时用温米饮送下,一昼夜五六服。    【主治】阴虚下痢五色,腹痛,至夜发热。    【禁忌】服药期间,忌食油腻。
阿胶散1    阿胶散1    【来源】《太平圣惠方》卷七十五。    【组成】阿胶23克(捣碎,炒令黄燥)白茯苓23克白术23克当归30克(锉,微炒)陈橘皮30克(汤浸,去白、瓤,焙)芎藭23克甘草7.5(炙微赤,锉)    【用法】上药捣筛为散。每服9克,以水250毫升,加生姜4克,大枣3枚,煎至150毫升,去滓,不计时候,稍热服。    【主治】妊娠胎动,腹中疠痛,不思饮食。
阿胶散2    阿胶散2    【来源】《小儿药证直诀》卷下。    【异名】补肺散((小儿药证直诀》卷下)、补肺阿胶散(《医方集解》)【组成】阿胶45克(麸炒)鼠粘子(炒香)甘草()7.5克马兜铃15克()杏仁7个(去皮、尖,炒)糯米30克()    【用法】上为末。每服36克,用水150毫升,煎至90毫升,食后温服。    【功用】养阴清肺,止咳平喘。    【主治】小儿肺虚有火,咳嗽气喘,咽喉干燥,咯痰不爽,或痰中带血,舌红少苔,脉浮细数。    【方论】方中重用阿胶滋阴养血为君,糯米、甘草健脾益气,培土生金为臣;马兜铃、牛蒡子清热降气,利膈化痰为佐;杏仁润肺化痰,止咳平喘为使。诸药合用,共奏养阴清肺,止咳平喘之效。
阿胶散3    阿胶散3    【来源】《三因极一病证方论》卷十三。    【组成】阿胶(麸炒)马兜铃各30克五灵脂()桑白皮各15克甘草()7.5克    【用法】上药研末。每服3克,用水150毫升,煎取90毫升,食后、临卧时通口服。    【主治】虚人老人一切咳嗽。
阿胶散4    阿胶散4    【来源】《妇人大全良方》卷十二。    【组成】熟地黄60克白芍药艾叶当归甘草阿胶黄耆各30克(一方有川芎)    【用法】上药哎咀。每服15克,用水300毫升,加生姜3片,大枣1个,煎至210毫升,去滓温服,无时。    【主治】妊娠不问月数深浅,或因跌仆,或因毒药,胎动不安,腰痛腹满;或胎漏下血,短气乏力者。
阿胶散5    阿胶散5    【来源】《医学心悟》卷三。    【组成】阿胶(水化开,冲服)3克丹参生地各6克黑山栀丹参血余(即乱发烧灰,存性)麦冬当归各2.4克    【用法】水煎服。    【主治】心移热于膀胱,迫血妄行,致患尿血,脉数,舌赤者。

我们给出prompt如下:

请根据给定的文本内容,识别并提取出以下类型的实体及其之间的关系:

方剂名称:例如“阿胶散5”,这是我们要记录的主要对象。
出处文献:如《医学心悟》卷三,指出该方剂首次记载于哪部著作中。
药物成分:列出所有提到的具体药材名称及用量,比如阿胶、丹参、生地等,并注明每种药材的具体剂量。
制备方法:描述如何准备这些药材,例如是否需要水化开、冲服或者特定的处理方式。
服用方式:说明如何使用此方剂,如“水煎服”。
适应症/主治功能:定义该方剂适用于治疗哪些病症或症状,如“心移热于膀胱,迫血妄行,致患尿血,脉数,舌赤者”。
请按照上述分类,将文本中的信息整理成结构化的形式,并确保每个实体与其相关联的关系都清晰表达出来。此外,请注意区分不同实体之间的层次关系,例如某些药材可能是作为主药出现,而其他则可能是辅料或其他角色。

最后,请确认所提取的信息准确反映了原文的意思,并且没有任何遗漏重要细节的情况,将结果输出为json格式。

这里我是将txt文本作为附件上传进去,采用深度搜索再执行的这段prompt

image.png

最终提取效果如下:

{
   
    "方剂名称": "阿胶地黄汤",
    "出处文献": "《太平圣惠方》卷三十七",
    "药物成分": [
      {
   
        "药材名称": "生干地黄",
        "剂量": "120克",
        "处理方式": ""
      },
      {
   
        "药材名称": "阿胶",
        "剂量": "60克",
        "处理方式": "(捣碎,炒令黄燥)"
      },
      {
   
        "药材名称": "蒲黄",
        "剂量": "60克",
        "处理方式": ""
      }
    ],
    "制备方法": "上药捣筛为散。每服9克,以水250毫升,入竹茹1鸡子大。煎至125毫升,去滓,食后温服。",
    "服用方式": "食后温服。",
    "适应症/主治功能": "热伤肺脏,唾血不止。"
  },

其实这里还可以更加细化一些,多拆分成几组,效果会更好

也可以只做简单的关系提取,比如只提取节点对节点的关系,继续给出prompt:

请你分析判断上述中存在的实体与实体间的关系,拆分成多组按照如下格式输出:
{
   
        "node_1": "处方\t鳖甲汤_1",
        "relation": "composition",
        "node_2": "中药名\t京三棱"
}

此时拆分后结果如下:

[
  {
   
    "node_1": "处方\t阿胶地黄汤",
    "relation": "composition",
    "node_2": "中药名\t生干地黄"
  },
  {
   
    "node_1": "处方\t阿胶地黄汤",
    "relation": "composition",
    "node_2": "中药名\t阿胶"
  },
  {
   
    "node_1": "处方\t阿胶地黄汤",
    "relation": "composition",
    "node_2": "中药名\t蒲黄"
  },
  {
   
    "node_1": "中药名\t阿胶",
    "relation": "dosage",
    "node_2": "剂量\t60克"
  },
  {
   
    "node_1": "中药名\t生干地黄",
    "relation": "dosage",
    "node_2": "剂量\t120克"
  },
  {
   
    "node_1": "中药名\t蒲黄",
    "relation": "dosage",
    "node_2": "剂量\t60克"
  },
  {
   
    "node_1": "中药名\t阿胶",
    "relation": "preparation",
    "node_2": "处理方式\t(捣碎,炒令黄燥)"
  },
  {
   
    "node_1": "处方\t阿胶地黄汤",
    "relation": "source",
    "node_2": "出处文献\t《太平圣惠方》卷三十七"
  },
  {
   
    "node_1": "处方\t阿胶地黄汤",
    "relation": "preparation_method",
    "node_2": "制备方法\t上药捣筛为散。每服9克,以水250毫升,入竹茹1鸡子大。煎至125毫升,去滓,食后温服。"
  },
  {
   
    "node_1": "处方\t阿胶地黄汤",
    "relation": "administration",
    "node_2": "服用方式\t食后温服。"
  },
  {
   
    "node_1": "处方\t阿胶地黄汤",
    "relation": "indications",
    "node_2": "适应症/主治功能\t热伤肺脏,唾血不止。"
  }
]

这种就是直接可以使用的数据了

下面准备到neo4j中进行展示

这里,周周要推荐一个极其优秀的开源项目https://github.com/BinNong/llm-graph-builder

image.png

为什么说极其优秀?因为真的特别特别方便

我们只需要在此处上传自己的实体关系文本,然后点击生成

image.png

在线版默认调用的是GPT和GEMINI,本地部署后可以支持通义等自定义模型

image.png

并且右侧还可以直接进行RAG形式的对话

image.png

因为我的提问是与文本无关的,所以这里提示没有找到对应的问题答案

为了节约时间,我这里缩减了很多内容,仅保留了上文中提到的结果,要不然140w字采用GPT-4o估计也得十几个小时

当完成之后,我们点击预览

image.png

最终结果如下所示:

defbb9ac-9658-4504-b305-a6e537eaa184.gif

剔除文件本身后,得到实体关系如下:

image.png
image.png
image.png

回到上传界面,可以看到提取的关系和实体节点数:

image.png

总结

本文从0出发,在短短三天内搭建出了知识图谱的基础框架,并对GraphRAG、LightRAG和Kotaemon这三种流行的图RAG架构进行了深入的比较分析。尽管取得了初步成果,但也必须清醒地看到,这个知识图谱的原型还存在许多局限性。

  • 构建知识图谱是一个复杂的过程,涉及到数据采集、实体识别、关系抽取、图谱存储等多个环节。在短短三天内完成的工作,更多的是概念验证和初步探索,而非一个成熟的解决方案。因此,这个雏形在数据的广度和深度、实体和关系的准确性、以及图谱的查询和推理能力等方面,都有很大的提升空间。

  • 在三款RAG架构的比较中虽然提供了一些洞见,但这些比较往往是基于特定的测试案例和有限的数据集进行的。在实际应用中,不同的架构可能在不同的场景和需求下表现出不同的优势和局限性。

  • 知识图谱的成功应用不仅取决于技术层面,还涉及到领域知识的深度整合、用户需求的准确把握以及生态系统的构建等多个方面。因此,未来的工作需要跨学科合作,结合中医药领域的专业知识,以及用户的实际需求,共同推动知识图谱的发展和应用。

相关文章
|
3月前
|
人工智能 自然语言处理 数据库
基于RAG和LLM的水利知识问答系统研究
随着全球水资源紧张加剧,我国面临严峻的水资源管理挑战。《十四五规划》提出构建智慧水利体系,通过科技手段提升水情测报和智能调度能力。基于大语言模型(LLM)的水利智能问答系统,利用自然语言处理技术,提供高效、准确的水利信息查询和决策支持,助力水资源管理智能化。该系统通过RAG技术和Agent功能,实现了对水利知识的深度理解和精准回答,适用于水利知识科普、水务治理建议及灾害应急决策等多个场景,推动了水利行业的信息化和智能化发展。
|
1月前
|
数据采集 前端开发 物联网
【项目实战】通过LLaMaFactory+Qwen2-VL-2B微调一个多模态医疗大模型
本文介绍了一个基于多模态大模型的医疗图像诊断项目。项目旨在通过训练一个医疗领域的多模态大模型,提高医生处理医学图像的效率,辅助诊断和治疗。作者以家中老人的脑部CT为例,展示了如何利用MedTrinity-25M数据集训练模型,经过数据准备、环境搭建、模型训练及微调、最终验证等步骤,成功使模型能够识别CT图像并给出具体的诊断意见,与专业医生的诊断结果高度吻合。
【项目实战】通过LLaMaFactory+Qwen2-VL-2B微调一个多模态医疗大模型
|
2月前
|
JSON 数据可视化 NoSQL
基于LLM Graph Transformer的知识图谱构建技术研究:LangChain框架下转换机制实践
本文介绍了LangChain的LLM Graph Transformer框架,探讨了文本到图谱转换的双模式实现机制。基于工具的模式利用结构化输出和函数调用,简化了提示工程并支持属性提取;基于提示的模式则为不支持工具调用的模型提供了备选方案。通过精确定义图谱模式(包括节点类型、关系类型及其约束),显著提升了提取结果的一致性和可靠性。LLM Graph Transformer为非结构化数据的结构化表示提供了可靠的技术方案,支持RAG应用和复杂查询处理。
166 2
基于LLM Graph Transformer的知识图谱构建技术研究:LangChain框架下转换机制实践
|
2月前
|
机器学习/深度学习 自然语言处理 PyTorch
从零开始构建nlp情感分析模型!
本教程介绍了如何使用PyTorch和Hugging Face的Transformers库构建一个情感分析模型。主要内容包括导入所需库、读取训练数据集、加载预训练的BERT模型和分词器、定义情感数据集类、划分训练集和验证集、创建数据加载器、设置训练参数、训练模型、评估模型性能以及定义和测试预测函数。通过这些步骤,可以实现一个简单而有效的情感分析模型。
254 2
|
3月前
|
机器学习/深度学习 自然语言处理 自动驾驶
深度学习之常识知识库构建
基于深度学习的常识知识库构建是一项旨在自动化获取和组织广泛的常识性信息的技术,它通过深度学习模型从文本、图像、语音等多种数据源中提取出隐含的常识知识,并构建一个可以被机器理解和应用的知识库。
68 4
|
4月前
|
搜索推荐 算法
模型小,还高效!港大最新推荐系统EasyRec:零样本文本推荐能力超越OpenAI、Bert
【9月更文挑战第21天】香港大学研究者开发了一种名为EasyRec的新推荐系统,利用语言模型的强大文本理解和生成能力,解决了传统推荐算法在零样本学习场景中的局限。EasyRec通过文本-行为对齐框架,结合对比学习和协同语言模型调优,提升了推荐准确性。实验表明,EasyRec在多个真实世界数据集上的表现优于现有模型,但其性能依赖高质量文本数据且计算复杂度较高。论文详见:http://arxiv.org/abs/2408.08821
113 7
|
3月前
|
机器学习/深度学习 人工智能 算法
人工智能-大语言模型-微调技术-LoRA及背后原理简介
人工智能-大语言模型-微调技术-LoRA及背后原理简介
72 0
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
【AI大模型】BERT模型:揭秘LLM主要类别架构(上)
【AI大模型】BERT模型:揭秘LLM主要类别架构(上)
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
【AI大模型】ChatGPT模型原理介绍(下)
【AI大模型】ChatGPT模型原理介绍(下)
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
【AI大模型】ChatGPT模型原理介绍(上)
【AI大模型】ChatGPT模型原理介绍(上)

热门文章

最新文章