本文将不依赖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)

        

        

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐