青训营×豆包MarsCode技术训练营 langchain对话大模型RAG检索增强生成实战尝试

153 阅读4分钟

RAG全称为Retrieval-Augmented Generation,即检索增强生成,它结合了检索和生成的能力,为文本序列生成任务引入外部知识。RAG将传统的语言生成模型与大规模的外部知识库相结合,使模型在生成响应或文本时可以动态地从这些知识库中检索相关信息。这种结合方法旨在增强模型的生成能力,使其能够产生更为丰富、准确和有根据的内容,特别是在需要具体细节或外部事实支持的场合。

在实现一个基于大语言模型的问答系统时,我经常会碰到一个问题,那就是大语言模型的泛用性似乎不全是好处。不管我问什么,它都会给出回答,可以称他为百科全书,但是现实使用时,我们很少需要百科全书,我们需要的是专业人士。当我问一些困扰我的专业问题时,大语言模型的回答就像在跟我绕圈子,总是自顾自地扯东扯西,真是听君一席话,如听一席话了。

随着越来越多地专业方向需要利用大语言模型提升工作效率,大语言模型地垂直应用更需要专业化,定制化。无论是我之前尝试的调用浏览器搜索工具也好,还是接下来我要学习的RAG检索增强生成也好,都是为了达到让大模型更加专业的目的。

接下来我将测试一个RAG的检索生成脚本,支持多种文档输入格式,直接上代码:

"""
"""
# 设置OpenAI的API密钥
import os
from volcenginesdkarkruntime import Ark
from typing import List, Any
from langchain.embeddings.base import Embeddings
from langchain.pydantic_v1 import BaseModel

# 初始化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


embeddings = DoubaoEmbeddings(
    model=os.environ["EMBEDDING_MODELEND"],
)

# 导入文档加载器模块,并使用TextLoader来加载文本文件
from langchain_community.document_loaders import TextLoader
from langchain_openai import ChatOpenAI  # ChatOpenAI模型

loader = TextLoader("./会议.txt", encoding="utf8")

# 使用VectorstoreIndexCreator来从加载器创建索引
from langchain.indexes import VectorstoreIndexCreator

index = VectorstoreIndexCreator(embedding=embeddings).from_loaders([loader])

llm = ChatOpenAI(model=os.environ["LLM_MODELEND"], temperature=0)

# 定义查询字符串, 使用创建的索引执行查询
query = "会议主题是什么?"
result = index.query(llm=llm, question=query)
print(result)  # 打印查询结果

# 替换成你所需要的工具
from langchain.text_splitter import CharacterTextSplitter

text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
from langchain_community.vectorstores import Qdrant

index_creator = VectorstoreIndexCreator(
    vectorstore_cls=Qdrant,
    embedding=embeddings,
    text_splitter=CharacterTextSplitter(chunk_size=1000, chunk_overlap=0),
)

不出意外的是,一上来就遇到了问题,volcenginesdkarkruntime这个包没有,直接用pip安装也是查无此包,看来是不愿意透露真实姓名的包啊。在一番CSDN查找下,总算锁定了它的真名。 pip install volcengine.然而安装后提示仍然没有volcenginesdkarkruntime包,好吧,手动上pypi上找了一圈,原来需要安装的是 volcengine-python-sdk。又试了半天,发现在windows环境中一直编译错误。这是我最烦的问题了,安装包的冲突导致的,很难解决。干脆直接转战到linux系统,这下终于安装好了。配置好各种apikey和环境变量后再次运行。终于有输出了。我将一个学术会议文档作为输入。

图片.png

可以看到总结的还是很到位的,唯一不满意的是回答太长了,好像直接抄下来的一样。接下来测试一下文档中没有相关内容会怎样。当问到玫瑰花的花语时,会输出 抱歉,我没有找到关于玫瑰花花语的相关内容,无法回答。但是如果不在文档中就无法回答的话,就是检索生成而不是检索增强生成了。再将问题变为“玫瑰花是植物吗?可以不查找文档”。得到输出 玫瑰花是植物。 看来在设计合理模板的情况还是能靠大模型自己回答的。如何把握检索与自主生成的界限也是需要思考的问题之一。

这篇文章就介绍到这里了,接下来的文章我将结合自己的数字人项目,探讨Langchain的拓展应用。感谢阅读。