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

技术

picture.image

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

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

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

picture.image

云搜索 VectorStore 准备

  1. 登录火山引擎云搜索服务,创建实例集群,集群版本选择 7.10.
  2. 在火山引擎方舟平台大模型广场选择合适的模型,并查看 API 调用说明

picture.image

  1. 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 准备

  1. 依赖安装

          
pip install volcengine --user
          
pip install langchain --user
      
  1. 初始化

          
#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 调用中看到样例。

picture.image


          
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**

picture.image

调用 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})
      

调试可以看到提示词:

picture.image

回答:

picture.image

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


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

picture.image

了解更多产品详情

点击【 阅读原文 】,了解更多产品详情。

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论