叶小钗

AI知识库效果不好?肯定RAG没用对

提供AI咨询+AI项目陪跑服务,有需要回复1

前情回顾:

  1. 聊聊与一体机同等级的智商税:AI知识库
  2. 其实RAG也是智商税,聊聊他与AI知识库的关系

最近总有AI知识库的2B咨询,所以昨天写了一篇关于RAG的文章,下来有同学对构建AI知识库的一些细节感兴趣,所以今天也简单说两句,在昨天RAG的基础上做展开。

今天就真的简单说两句了,这里还是以医疗场景为例,展示如何处理医学文献的向量化分割与存储、并通过RAG框架进行查询和调用。

这个过程将包括文献的预处理、向量化、存储、检索和生成模型调用等环节。

简单的RAG案例

假设有一篇关于“糖尿病治疗的最新进展”的医学文献,我们要通过RAG框架来处理这篇文献。

一、文献预处理

首先,我们需要对文献进行预处理,清洗文本并转换为合适的格式。假设文献内容如下:

糖尿病是一种常见的慢性疾病,近年来,糖尿病的治疗方法取得了显著进展。在药物治疗方面,SGLT2抑制剂、GLP-1受体激动剂等新药物已成为治疗2型糖尿病的重要手段。最新研究表明,SGLT2抑制剂可显著降低心血管事件的发生率,并改善肾功能。

预处理就是将一些重复、多余的标签去掉。

文本分块

接下来,我们会对文献进行分块,根据文献的结构,我们可以选择语义分块,以保持每个块的完整性和语义连贯:

  1. 段落1: 糖尿病的背景介绍及治疗进展
  2. 段落2: 新药物的介绍:SGLT2抑制剂与GLP-1受体激动剂
  3. 段落3: 最新研究结果:SGLT2抑制剂的效果

每个段落成为一个分块,然后,每个段落会被向量化以生成嵌入向量。

三、向量化

对于每个分块,我们使用医学类模型(如BioBERT)将文本转化为向量。

PS:成熟的公司,会有个自己的小模型做向量化,现在比较好的模型是Qwen32B

假设我们使用以下Python代码来生成向量:

from transformers import BertTokenizer, BertModel
import torch

# 加载BioBERT模型和tokenizer
tokenizer = BertTokenizer.from_pretrained('dmis-lab/biobert-v1.1')
model = BertModel.from_pretrained('dmis-lab/biobert-v1.1')

# 文本分块(从文献中提取的每个段落)
paragraphs = [
"糖尿病是一种常见的慢性疾病,近年来,糖尿病的治疗方法取得了显著进展。",
"在药物治疗方面,SGLT2抑制剂、GLP-1受体激动剂等新药物已成为治疗2型糖尿病的重要手段。",
"最新研究表明,SGLT2抑制剂可显著降低心血管事件的发生率,并改善肾功能。"
]

# 定义一个函数来处理文本并获取嵌入向量
def get_embedding(text):
    inputs = tokenizer(text, return_tensors='pt')
    with torch.no_grad():
        outputs = model(**inputs)
# 获取[CLS] token的输出作为文本嵌入
return outputs.last_hidden_state.mean(dim=1)

# 对每个段落进行向量化
embeddings = [get_embedding(paragraph) for paragraph in paragraphs]

# 打印每个段落的向量(嵌入向量)
for i, embedding in enumerate(embeddings):
print(f"段落{i+1}的向量:", embedding)

该代码将文本转化为一个嵌入向量,该向量包含了文本的语义信息。假设返回的嵌入向量用于后续的检索。

三、存储向量

将每个段落生成的向量存储到向量数据库(如FAISS)中:

将每个段落生成的向量存储到向量数据库(如FAISS)中。以下是如何使用FAISS存储和检索向量的代码:

import faiss
import numpy as np

# 假设已生成的文本嵌入保存在一个numpy数组中
embedding_1 = embeddings[0].numpy()  # 转换为numpy数组
embedding_2 = embeddings[1].numpy()
embedding_3 = embeddings[2].numpy()

# 将所有嵌入向量组合成一个数组
all_embeddings = np.vstack([embedding_1, embedding_2, embedding_3])

# 创建FAISS索引
dim = all_embeddings.shape[1]  # 向量的维度
index = faiss.IndexFlatL2(dim)  # 使用L2距离度量

# 将嵌入向量添加到索引中
index.add(all_embeddings)

# 假设我们有一个查询向量(例如用户的问题:“糖尿病的最新药物有哪些?”)
query_embedding = get_embedding("糖尿病的最新药物有哪些?").numpy()

# 查询:找到与查询向量最相似的文档块
D, I = index.search(query_embedding, k=3)  # 查询最相似的3个向量
print(f"最相关的文档索引:{I}")

这段代码通过FAISS将三个段落的向量存储到索引中,并使用一个查询向量来检索与之最相关的文档块。

四、检索和生成调用

在检索过程中,FAISS会返回与查询向量最相关的文档块的索引。

假设我们查询的文本是“糖尿病的最新药物有哪些?”,FAISS返回的索引可能指向第二个段落(关于SGLT2抑制剂和GLP-1受体激动剂的介绍)。

我们将使用这些检索到的段落作为生成模型的提示词,假设使用一个生成模型(如GPT)生成回答:

# 假设检索到的相关段落
relevant_paragraph = paragraphs[1]  # 第二段(SGLT2抑制剂和GLP-1受体激动剂)
# 生成模型的输入
prompt = f"根据以下文献内容,回答用户提问:\n{relevant_paragraph}\n\n问题:糖尿病的最新药物有哪些?"

# 假设我们使用GPT模型生成回答(以下为伪代码)
generated_answer = "根据最新的研究,SGLT2抑制剂和GLP-1受体激动剂是治疗2型糖尿病的有效药物。"

print(generated_answer)

最终效果

通过以上过程,用户查询“糖尿病的最新药物有哪些?”时,系统首先通过RAG框架进行检索,从向量化后的医学文献中找到最相关的段落,然后生成模型结合相关信息输出一个精准的回答。

通过这个完整的过程,各位可以实现从医学文献中提取相关信息并生成回答,帮助解决医疗相关问题。

如何让RAG好用

以上案例是比较简单的,真实情况会复杂很多,因为需要保证医学文献的质量和时效性就需要不断更新,意思RAG的维护也是一个长期的过程。

为了应对医学文献快速发展的挑战,系统需要定期更新医学文献数据库,并确保能够覆盖最新的研究成果。

例如,可以设置一个自动化的系统来定期从PubMed、Google Scholar等数据库抓取最新的糖尿病治疗研究文献,并对其进行向量化和存储。

定期的更新能够有效解决医学领域知识的时效性问题,确保系统基于最新的研究提供决策支持。

PS:各位同学在处理这个的时候,要特别注意版权问题

在RAG系统中,虽然文献检索通过向量数据库实现高效检索,但这并没有完全解决文献时效性问题。

为了使系统的检索结果更加精准,可以引入时效性过滤机制。

例如,对于糖尿病治疗方案相关文献,可以设定系统仅检索过去5年内的文献,剔除过时的研究数据。

这不仅提高了决策的时效性,还避免了将过时的治疗方法引入当前的临床决策中。

要注意,这里真实的意思是在做数据导入的时候,要加入各种筛选标签,以便你能拿到更合理的数据

比如可以在检索阶段加入更多的相关性评估机制。除了传统的相似度评分,还可以根据查询的医学术语与文献中提及的术语的匹配度进行加权。

这里举个实际的例子,通过分析问题和文献中的医学术语(例如通过UMLS的医学术语库提取),系统可以基于术语的匹配度重新排序检索结果。

对于特定查询(如“新诊断2型糖尿病患者,BMI 28,应如何制定初始治疗方案?”),系统可以通过识别查询中的医学术语(如“2型糖尿病”,“BMI”,“治疗方案”等)与文献中的相关术语匹配,从而增强文献检索的精准性。

另外在医学领域,一个治疗方案往往包含多个层次的证据支持。

RAG系统可以整合来自不同来源(如临床指南、学术文献和医院内部规范)的信息,构建出更为全面的治疗方案。

例如,如果一篇研究文献指出某种药物能有效治疗糖尿病,而另一篇文献则详细描述了药物的副作用,系统可以在提供治疗建议时,结合这两篇文献的内容,帮助医生做出更全面的决策。

事实上,知识图谱能够有效的提升RAG的召回率,而且在更新一块的能力更友好。

知识图谱

知识图谱是通过图的方式表示和存储知识的一种方法,其中图中的节点表示实体(如疾病、药物、症状等),边表示实体之间的关系(如“治疗”,“并发症”,“作用于”)。

知识图谱本身通过图的结构存储实体及其关系,在很多应用场景下,它可以直接支持高效的搜索和推理,并且其查询效率通常比传统的向量化检索要高,因为它使用的是图数据库中的结构化索引(如基于邻接矩阵、哈希表、图遍历算法等)。

这种结构使得图谱可以直接通过图的连接性进行推理和查询,而不需要通过向量化步骤。

但要注意,虽然知识图谱本身通过其结构关系可以高效地进行查询和推理,但在实际应用中,尤其是在与RAG框架结合时,仍然可能需要一定的向量化处理。这里的原因有几个方面:

  1. 在实际应用中,RAG系统不仅依赖知识图谱,还会从其他来源(如医学文献、电子健康记录等)检索信息。这些信息通常是非结构化的文本,需要向量化处理;
  2. 知识图谱擅长在已知领域内进行推理(例如医学知识、药物与疾病的关系等),但在面对新兴领域或未知的关系时,知识图谱的作用可能会受到限制;

所以,AI知识库又多了一个知识点,知识图谱了,不过不用担心,图谱这块通用框架很多,比如Neo4j、Apache Jena、GraphDB等,大家下来自己去了解吧

结语

今天,我们简单探讨了如何利用RAG框架与知识图谱处理医学文献并生成决策支持答案,展示了在糖尿病治疗场景中的具体应用。

然而,其实这里面的水很深的,比如:

  1. 关于版权问题、文献时效性更新及质量控制的操作细节可以进一步完善;
  2. 知识图谱与RAG的结合、模型微调及生成模型验证的细节也需要更深入的讨论;

在未来的讨论中,我们将继续补充这些方面的内容,进一步优化技术实现,解决实际应用中的挑战,以提供更全面的AI知识库解决方案。

Image