文章目录
概要
该博客将解释如何使用langchain实现一个基于 RAG(检索增强生成)的问答(QA)系统。通过本博客,你将了解从 JSON 文件读取数据、向向量数据库添加文档、进行相似性检索、以及通过大语言模型生成回答的过程。
整体架构流程
1. 加载 JSON 数据
import json
# 定义 JSON 文件路径
file_path = "/dataset/test_m3e.json" # 替换为实际的 JSON 文件路径
# 打开并读取 JSON 文件
with open(file_path, 'r', encoding='utf-8') as f:
json_data = json.load(f)
# 提取 "input" 和 "output" 字段作为 query 和 answer
query = [item['input'] for item in json_data]
answer = [item['output'] for item in json_data]
说明:
- 该代码首先定义文件路径并加载 JSON 文件。
- JSON 文件中的
input
代表查询内容,output
是对应的回答。
2. 创建文档对象并添加元数据
from langchain_core.documents import Document
# 创建包含 query 和 answer 的文档对象列表
docs = [Document(page_content=query, metadata={'answer': answer}) for query, answer in zip(query, answer)]
# 打印调试信息
print(f"Number of documents: {len(docs)}")
for i, doc in enumerate(docs):
print(f"Document {i}: {doc}")
说明:
- 这里通过
Document
对象将查询内容和回答进行配对并封装。page_content
存储查询内容,metadata
中的answer
是对应的回答。 - 此步骤便于后续检索时关联查询和答案。
3. 初始化嵌入模型
from langchain_huggingface import HuggingFaceEmbeddings
# 使用 HuggingFace 的 m3e 基础嵌入模型
embeddings = HuggingFaceEmbeddings(model_name="moka-ai/m3e-base") #亦可以将embedding model 部署到本地
说明:
- 使用
HuggingFaceEmbeddings
类来加载m3e
(m3e中文语料库训练)嵌入模型。 - 嵌入模型负责将文本转换成向量表示,以便后续的相似性检索。
4. 初始化 Chroma 向量存储
from langchain_chroma import Chroma
# 初始化 Chroma 向量数据库
vector_store = Chroma(
collection_name="aied_v1",
embedding_function=embeddings,
persist_directory="./chroma_db_test_m3e" # 可选:存储数据的本地目录
)
说明:
- 使用 Chroma 向量存储来保存嵌入向量数据,并指定了保存的目录,以便持久化存储数据。
5. 向向量数据库添加文档
from uuid import uuid4
# 为每个文档生成唯一ID
uuids = [str(uuid4()) for _ in range(len(docs))]
# 将文档添加到向量数据库中
vector_store.add_documents(documents=docs, ids=uuids)
说明:
- 为每个文档生成唯一的 UUID,以确保数据库中的每个记录都是唯一的。
- 使用
add_documents
方法将所有文档存储到 Chroma 向量数据库中。
6. 基于相似度检索文档
# 使用向量数据库进行文本相似性检索
results = vector_store.similarity_search("德育教育", k=2)
for res in results:
print(f"* {res.page_content} [{res.metadata}]")
说明:
- 使用
similarity_search
方法进行查询,返回与“德育教育”最相似的文档。 - 设置参数
k=2
以限制返回的文档数量为2个。
7. 通过嵌入向量检索相似文档
# 使用嵌入向量进行检索
results = vector_store.similarity_search_by_vector(
embedding=embeddings.embed_query("德育含义"), k=1
)
for doc in results:
print(f"* {doc.page_content} [{doc.metadata}]")
说明:
similarity_search_by_vector
方法通过嵌入向量检索相似文档,适合预先已生成向量的查询。- 该方法比直接文本检索更高效,特别适用于大数据量环境下的相似性计算。
8. 初始化检索器
retriever = vector_store.as_retriever(
search_type="mmr", search_kwargs={"k": 1, "fetch_k": 2}
)
说明:
- 初始化检索器以便用于 RAG。
- 使用 MMR(最大边际相关性)作为检索方式,参数
k=1
指定返回1个结果,fetch_k=2
表示最多检索2个结果。
9. 加载 RAG 提示模板
from langchain import hub
# 从 hub 中加载预定义的 RAG 提示模板
prompt = hub.pull("rlm/rag-prompt") #也可以通过提示工程自定义提示模版
说明:
- 加载用于 RAG 的提示模板,该模板定义了生成回答的输入输出格式。
- 该模板将用于生成答案的格式化。
10. 定义 RAG 链并生成回答
from langchain_community.chat_models import ChatZhipuAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# 初始化大语言模型
llm = ChatZhipuAI(
temperature=0.5,
model="glm-4",
api_key="xxx"
)
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
# 定义 RAG 链并进行文档格式化、提示、生成回答
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 使用 RAG 链生成回答
rag_chain.invoke("什么是德育含义?")
说明:
- RAG 链将检索结果格式化并通过提示模板提供给语言模型生成回答。
format_docs
函数用于将文档内容格式化为连续文本。- 使用
invoke
方法传入问题,并通过StrOutputParser
解析生成的答案。
总结
通过上述步骤,我们完成了 RAG 的代码实现,包括:
- 加载数据
- 嵌入向量生成与存储
- 向量相似性检索
- 使用提示模板和检索所得文档和大语言模型生成回答
技术名词解释
提示:这里可以添加技术名词解释
例如:
- Chroma
小结
后续会基于gradio搭建完整的QA系统
标签:检索,RAG,docs,langchain,QA,文档,import,向量 From: https://blog.csdn.net/qq_44742936/article/details/143577202