从0开始手动搭建一个简易RAG系统
本文将不依赖langchain等框架,从零搭建一个简易RAG系统,帮助理解RAG系统原理。
一、相关概念
RAG(Retrieval Augmented Generation 检索增强生成),工作流程如下:

其中最核心的概念是Embedding,其作用为将文字转换成数字向量,方便计算相关性。
计算相关性则需要使用余弦相似度。(概念性内容文中不做展开解释,可自行前往查询)
二、环境安装
终端执行以下指令:
pip install sentence-transformers
安装完成后,还需要安装向量模型,需要在程序中执行。
三、代码
先导入所需包
from openai import OpenAI
from sentence_transformers import SentenceTransformer
from sentence_transformers.util import cos_sim
项目中,最重要的一环就是知识库构建,我们要线构建好知识库,在后续检索的过程中才能更方便,也不容易报错。
创建知识库类:
class knowledgeBase:
pass
初始化知识库:
def __init__(self):
# 存放所有已添加的知识文档
self.knowledge = []
# 初始化句向量模型,用于编码文本
self.model = SentenceTransformer('BAAI/bge-m3')
选择的模型是针对中文计算向量的模型,首次运行是会下载模型,大小约2.7G,请提前留好空间防止报错。
其中的self非常的重要,self相当于这个实例绑定专属变量,实现每个实例数据互不干扰,在使用当前类创建对象时,python会自动把新建的实例传给self。
在知识库中,我们要存储好数据,首先要设定好数据的格式,拿维修系统举例,维修手册中的数据格式一般是:
"code": "E101",
"description": "温度过高",
"solution": "检查散热系统"
了解数据格式之后,我们为知识库添加方法,实现向数据库中添加数据的功能,一般我们向列表中添加元素,为了使后续遍历文档的时候减少等待时间,我们可以提前计算知识库中元素的向量,提前存进知识库中:
计算向量,针对的是文本,所以我们要先将文档中的元素拼接成一段文本:
text = document['code'] + document['description'] + document['solution']
计算向量所使用的函数为:model.encode(text),我们之前选择的model是针对中文字符的向量计算模型,使用中文知识库。
完整代码如下:
def add_document(self, document):
# 将文档的代码、描述和解决方案拼接成一段文本
text = document['code'] + document['description'] + document['solution']
# 计算文本向量
embedding = self.model.encode(text)
# 将向量存入文档中,方便后续检索
document['embedding'] = embedding
self.knowledge.append(document)
到这,我们就已经将知识库中的元素全部计算出向量了。
向量的作用是,让大模型能够知道,两个词之间是相关的,如果我们直接输入“发动机”,但是知识手册中存储的是“引擎”,这时候就需要计算“余弦相似度”来检索出知识库中与用户输入最相关的数据。
余弦相似度计算函数为:
score = model.encode(query,doc["embedding"])
结果越大,相似度越高,证明越相关
接下来我们来写最重要的检索类:
def search(self, query):
pass
当我们得到用户输入后,我们为了计算余弦相似度,要先将用户输入转换成向量:
query_embedding = self.model.encode(query)
得到用户输入向量之后,遍历知识库,找到其中最相关的一个:
best_score = -1
best_document = None
# 遍历所有知识文档,找到与查询最相似的一个
for document in self.knowledge:
score = cos_sim(query_embedding, document['embedding']).item()
if score > best_score:
best_score = score
best_document = document
到这,整个检索过程就结束了,完整代码如下:
def search(self, query):
# 对查询进行编码
query_embedding = self.model.encode(query)
best_score = -1
best_document = None
# 遍历所有知识文档,找到与查询最相似的一个
for document in self.knowledge:
score = cos_sim(query_embedding, document['embedding']).item()
if score > best_score:
best_score = score
best_document = document
return best_document, best_score
我们现在得到了用户输入和知识库中和用户输入最相关的数据,下一步就是组合提示词,发送给大模型。创建提示词类:
def build_prompt(self, document, query):
pass
为了提升大模型返回结果的准确性,我们要将检索到的知识库数据和用户输入组装在一起发送给大模型,完整代码如下:
def build_prompt(self, document, query):
# 将检索到的知识库内容与用户问题整合成给大模型的提示词
prompt = f"""
你是一名工业设备维修专家。 请根据知识库内容回答问题。
知识库内容:
故障代码:{document['code']},
故障描述:{document['description']},
解决方案:{document['solution']}。
问题:
{query}。
请给出详细的解决方案。
"""
return prompt
之后就是创建大模型链接类,因为不同厂家连接方式不同,这里不做解释,直接给出完整代码(以openai为例):
class LLMClient:
def __init__(self, api_key):
self.client = OpenAI(
api_key=api_key,
base_url="你的大模型网站"
)
# 模型名称,可根据实际情况更换
self.model = "gpt-5.5"
def chat(self, prompt):
# 使用 OpenAI 的 responses 接口创建聊天响应
response = self.client.responses.create(
model=self.model,
input=prompt,
)
# 返回模型输出的文本内容
return response.output_text
至此,准备工作全部完成,我们创建一个测试:
# 以下为示例流程:
# 1. 创建知识库并添加示例故障文档
kb = KnowledgeBase()
kb.add_document(
{
"code": "E101",
"description": "温度过高",
"solution": "检查散热系统"
}
)
kb.add_document(
{
"code": "E102",
"description": "温度传感器异常",
"solution": "检查传感器线路"
}
)
kb.add_document(
{
"code": "E103",
"description": "设备通信失败",
"solution": "检查网络连接"
}
)
# 2. 构建查询并检索最相似的知识文档
query = "加热探头坏了"
document, score = kb.search(query)
print(document)
print(score)
# 3. 根据检索结果生成给模型的提示词
prompt = kb.build_prompt(document, query)
# 4. 调用大模型生成回答
llm = LLMClient(api_key="你的apikey")
answer = llm.chat(prompt)
# 5. 输出模型回答
print(answer)
输出结果:

四、完整代码:
from openai import OpenAI
from sentence_transformers import SentenceTransformer
from sentence_transformers.util import cos_sim
# 知识库类,用于存储文档、计算向量并根据查询匹配最相关的文档
class KnowledgeBase:
def __init__(self):
# 存放所有已添加的知识文档
self.knowledge = []
# 初始化句向量模型,用于编码文本
self.model = SentenceTransformer('BAAI/bge-m3')
def add_document(self, document):
# 将文档的代码、描述和解决方案拼接成一段文本
text = document['code'] + document['description'] + document['solution']
# 计算文本向量
embedding = self.model.encode(text)
# 将向量存入文档中,方便后续检索
document['embedding'] = embedding
self.knowledge.append(document)
def search(self, query):
# 对查询进行编码
query_embedding = self.model.encode(query)
best_score = -1
best_document = None
# 遍历所有知识文档,找到与查询最相似的一个
for document in self.knowledge:
score = cos_sim(query_embedding, document['embedding']).item()
if score > best_score:
best_score = score
best_document = document
return best_document, best_score
def build_prompt(self, document, query):
# 将检索到的知识库内容与用户问题整合成给大模型的提示词
prompt = f"""
你是一名工业设备维修专家。 请根据知识库内容回答问题。
知识库内容:
故障代码:{document['code']},
故障描述:{document['description']},
解决方案:{document['solution']}。
问题:
{query}。
请给出详细的解决方案。
"""
return prompt
# 大模型客户端,用于调用 OpenAI API
class LLMClient:
def __init__(self, api_key):
self.client = OpenAI(
api_key=api_key,
base_url="你的大模型网站"
)
# 模型名称,可根据实际情况更换
self.model = "gpt-5.5"
def chat(self, prompt):
# 使用 OpenAI 的 responses 接口创建聊天响应
response = self.client.responses.create(
model=self.model,
input=prompt,
)
# 返回模型输出的文本内容
return response.output_text
# 以下为示例流程:
# 1. 创建知识库并添加示例故障文档
kb = KnowledgeBase()
kb.add_document(
{
"code": "E101",
"description": "温度过高",
"solution": "检查散热系统"
}
)
kb.add_document(
{
"code": "E102",
"description": "温度传感器异常",
"solution": "检查传感器线路"
}
)
kb.add_document(
{
"code": "E103",
"description": "设备通信失败",
"solution": "检查网络连接"
}
)
# 2. 构建查询并检索最相似的知识文档
query = "加热探头坏了"
document, score = kb.search(query)
print(document)
print(score)
# 3. 根据检索结果生成给模型的提示词
prompt = kb.build_prompt(document, query)
# 4. 调用大模型生成回答
llm = LLMClient(api_key="你的apikey")
answer = llm.chat(prompt)
# 5. 输出模型回答
print(answer)
更多推荐


所有评论(0)