Langchain实践指南:实现一个RAG工作流 | 豆包MarsCode AI刷题

16 阅读3分钟

RAG(Retriever Augmented Generation)工作流简介

检索增强生成(RAG)是一种将检索和生成相结合的技术,特别适合需要根据具体知识或文档库提供准确回答的任务。在构建大模型工作流时,RAG可以显著减少大模型“幻觉”的出现,即生成错误或无关答案的可能性。RAG通过向量化的方式检索相关文档作为上下文,为生成模型提供准确的答案依据。

1. 初始化Embedding类

为了能够对文本进行向量化,我们首先初始化一个DoubaoEmbeddings类,用于生成向量化的嵌入数据。以下代码展示了如何构建一个基础的Embedding类:

# 初始化Embedding类
class DoubaoEmbeddings(BaseModel, Embeddings):
    client: Ark = None
    api_key: str = ""
    model: str

    def __init__(self, **data: Any):
        super().__init__(**data)
        if self.api_key == "":
            self.api_key = os.environ["OPENAI_API_KEY"]
        self.client = Ark(
            base_url=os.environ["OPENAI_BASE_URL"],
            api_key=self.api_key
        )

    def embed_query(self, text: str) -> List[float]:
        """
        生成输入文本的 embedding.
        Args:
            texts (str): 要生成 embedding 的文本.
        Return:
            embeddings (List[float]): 输入文本的 embedding,一个浮点数值列表.
        """
        embeddings = self.client.embeddings.create(model=self.model, input=text)
        return embeddings.data[0].embedding

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        return [self.embed_query(text) for text in texts]

    class Config:
        arbitrary_types_allowed = True

在代码中,我们通过embed_queryembed_documents方法分别对单个文本和多个文档进行嵌入处理,将文本数据转换成向量数据。这些向量数据在后续的检索步骤中用于相似度计算。

2. 文档加载与切分

在进行RAG之前,首先要加载并切分文档,使其符合模型输入的大小要求。以下代码实现了text_loader文档加载器以及文档切分与向量数据库创建的函数create_vector_db

def text_loader(url):
    # 文本文档加载器
    loader = TextLoader(url)
    docs = loader.load()
    return docs

def create_vector_db(data_path, db_path, loader):
    text_splitter = CharacterTextSplitter(chunk_size=2048)
    data = loader(data_path)
    docs = text_splitter.split_documents(data)
    db = FAISS.from_documents(docs, embeddings)
    db.save_local(db_path)  # 保存路径

在这里,通过CharacterTextSplitter将文本切分为固定大小的块,以适应模型输入要求。

3. 创建问答生成模板和RAG流程

创建一个问题生成模板,帮助模型基于检索到的上下文内容生成准确的回答。下面代码展示了如何构建问题模板以及如何使用向量数据库进行检索:

def rag(msg):
    prompt = ChatPromptTemplate.from_template(
        """
        以下问题基于提供的 context,分析问题并给出合理的建议回答:
        <context>
        {context}
        </context>
        Question: {input}
        """
    )

    new_db = Qdrant.load_local("db", embedder, allow_dangerous_deserialization=True)
    document_chain = create_stuff_documents_chain(llm, prompt)
    retriever = new_db.as_retriever()  # 从向量数据库中检索
    retrieval_chain = create_retrieval_chain(retriever, document_chain)
    gpt_response = retrieval_chain.invoke({"input": msg})
    response = gpt_response['answer']

    return response

在这个流程中,new_db.as_retriever()调用从本地加载的向量数据库进行检索,找到与输入问题相关的文档。通过create_stuff_documents_chaincreate_retrieval_chain方法实现生成模型与检索系统的结合。

结论

本文通过具体代码示例和注释,展示了如何使用RAG构建一个检索增强的生成工作流。RAG通过结合检索和生成功能,在提高模型回答准确性的同时,也可以避免模型幻觉的出现,是构建智能对话、问答等系统的有效手段。