5分钟,结合 LangChain 搭建自己的生成式智能问答系统

伴随大语言模型(LLM,Large Language Model)的涌现,人们发现生成式人工智能在非常多领域具有重要意义,如图像生成,书写文稿,信息搜索等。随着 LLM 场景的多样化,大家希望 LLM 能在垂直领域发挥其强大的功能。但是由于大模型在特定领域数据集的训练和时效性限制,在 LLM 的基础上构建垂直领域的产品时,需要将特定的知识库输入到大模型中来训练或者推理。

目前常用的方式有两种:微调(Fine-Tuning),提示学习(Prompt-Tuning)。前者是通过新数据集在已有模型上进一步训练,训练成本较高,时效性较差。后者在训练成本,时效性上都比较灵活。

本文将基于提示学习方式,介绍如何基于火山引擎云搜索服务和方舟平台来构建专属的智能问答系统。利用嵌入技术(embedding),通过嵌入模型,将数据集内容转化为向量,然后借助火山引擎云搜索服务 ESCloud 的向量搜索能力,将这些向量和数据保存起来。在查询阶段,通过相似度查询,匹配出关联的 topK 结果,然后将这些结果辅以提示词提供给 LLM,最终生成相应的答案。这里会从火山引擎方舟平台大模型广场中选取一个大模型作为 LLM 来推理答案。选用开源框架 LangChain 作为构建端到端语言模型应用框架,简化整个聊天模型的链路。

云搜索 VectorStore 准备

  • 登录火山引擎云搜索服务,创建实例集群,集群版本选择 7.10.
  • 在火山引擎方舟平台大模型广场选择合适的模型,并查看API调用说明
  • Mapping 准备
  • PUT langchain_faq
    {
    "mappings": {
    "properties": {
    "message": { "type": "text" },
    "message_embedding": { "type": "knn_vector", "dimension": 768 },
    "metadata": { "type": "text" }
    }
    },
    "settings": {
    "index": {
    "refresh_interval": "10s",
    "number_of_shards": "3",
    "knn": true,
    "knn.space_type": "cosinesimil",
    "number_of_replicas": "1"
    }
    }
    }

    Client 准备

  • 依赖安装
  • pip install volcengine --user
    pip install langchain --user
  • 初始化
  • #Embedding
    from langchain.embeddings import HuggingFaceEmbeddings
    #VectorStore
    from langchain.vectorstores import OpenSearchVectorSearch
    #LLM Base
    from langchain.llms.base import LLM
    #Document loader
    from langchain.document_loaders import WebBaseLoader
    #LLM Cache
    from langchain.cache import InMemoryCache
    #Volcengine
    from volcengine.ApiInfo import ApiInfo
    from volcengine import Credentials
    from volcengine.base.Service import Service
    from volcengine.ServiceInfo import ServiceInfo
    import json
    import os
    from typing import Optional, List, Dict, Mapping, Any
    #加载Embeddings,这里使用huggingFace 作为embedding
    embeddings = HuggingFaceEmbeddings()
    # 启动llm的缓存
    llm_cache = InMemoryCache()

    MaaS 准备

    我们从火山引擎方舟大模型平台中选取一个模型,这个步骤可以在选择模型后右上角的 API 调用中看到样例。

    maas_host = "maas-api.ml-platform-cn-beijing.volces.com"
    api_chat = "chat"
    API_INFOS = {api_chat: ApiInfo("POST", "/api/v1/" + api_chat, {}, {}, {})}
    class MaaSClient(Service):
    def __init__(self, ak, sk):
    credentials = Credentials.Credentials(ak=ak, sk=sk, service="ml_maas", region="cn-beijing")
    self.service_info = ServiceInfo(maas_host, {"Accept": "application/json"}, credentials, 60, 60, "https")
    self.api_info = API_INFOS
    super().__init__(self.service_info, self.api_info)
    client = MaaSClient(os.getenv("VOLC_ACCESSKEY"), os.getenv("VOLC_SECRETKEY"))
    #引入LLM Base,构造Volc GLM Client, 用于和LLM 对话
    from langchain.llms.base import LLM
    class ChatGLM(LLM):
    @property
    def _llm_type(self) -> str:
    return "chatglm"
    def _construct_query(self, prompt: str) -> Dict:
    query = "human_input is: " + prompt
    return query
    @classmethod
    def _post(cls, query: Dict) -> Any:
    request = ({
    "model": {
    "name": "chatglm-130b"
    },
    "parameters": {
    "max_tokens": 2000,
    "temperature": 0.8
    },
    "messages": [{
    "role": "user",
    "content": query
    }]
    })
    print(request)
    resp = client.json(api=api_chat, params={}, body=json.dumps(request))
    return resp
    def _call(self, prompt: str,
    stop: Optional[List[str]] = None) -> str:
    query = self._construct_query(prompt=prompt)
    resp = self._post(query=query)
    return resp

    写入数据集

    这里我们利用 LangChain 的 Loader 导入一些 Web 的数据集,然后利用 HuggingFaceEmbeddings (768 维度)生成特征值。用 VectorStore 写入云搜索服务 ESCloud 的向量索引。

    # Document loader
    from langchain.document_loaders import WebBaseLoader
    loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
    data = loader.load()
    # Split
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    text_splitter = RecursiveCharacterTextSplitter(chunk_size = 500, chunk_overlap = 0)
    all_splits = text_splitter.split_documents(data)
    #Embeddings
    from langchain.embeddings import HuggingFaceEmbeddings
    embeddings = HuggingFaceEmbeddings()
    #VectorStore
    # URL 为云搜索VectorStore的访问URL,
    # http_auth 为访问云搜索的用户密码
    from langchain.vectorstores import OpenSearchVectorSearch
    vectorstore = OpenSearchVectorSearch.from_documents(
    documents = all_splits,
    embedding = HuggingFaceEmbeddings(),
    opensearch_url = "URL",
    http_auth = ("user", "password"),
    verify_certs = False,
    ssl_assert_hostname = False,
    index_name = "langchain_faq",
    vector_field ="message_embedding",
    text_field = "message",
    metadata_field = "message_metadata",
    ssl_show_warn = False,)

    查询 + Retriever

    query = "What are the approaches to Task Decomposition?"
    docs = vectorstore.similarity_search(
    query,
    vector_field="message_embedding",
    text_field="message",
    metadata_field="message_metadata",)
    retriever = vectorstore.as_retriever(search_kwargs={"vector_field": "message_embedding", "text_field":"message", "metadata_field":"message_metadata"})

    LLM Chat

    这里选择了大模型平台中的 ChatG**

    调用 ChatAPI,这里会使用 LangChain 自带的 Prompt,结合 Query,给 LLM 然后发送出去。

    from langchain.chains import RetrievalQA
    llm = ChatGLM()
    retriever = vectorstore.as_retriever(search_kwargs={"vector_field": "message_embedding", "text_field":"message", "metadata_field":"message_metadata"})
    qa_chain = RetrievalQA.from_chain_type(llm,retriever=retriever)
    qa_chain({"query": query})

    调试可以看到提示词:

    回答:

    以上就是基于火山引擎云搜索服务和方舟平台构建专属智能问答系统的实践,欢迎大家登陆火山引擎控制台操作!

    云搜索服务 ESCloud 兼容 Elasticsearch、Kibana 等软件及常用开源插件,提供结构化、非结构化文本的多条件检索、统计、报表,可以实现一键部署、弹性扩缩、简化运维,快速构建日志分析、信息检索分析等业务能力。

    了解更多产品详情:www.volcengine.com/product/es