天天看點

5分鐘,結合 LangChain 搭建自己的生成式智能問答系統

作者:技術聯盟總壇

雲原生計算 火山引擎開發者社群 2023-07-21 17:01 發表于北京

點選上方藍字關注我們!

5分鐘,結合 LangChain 搭建自己的生成式智能問答系統

伴随大語言模型(LLM,Large Language Model)的湧現,人們發現生成式人工智能在非常多領域具有重要意義,如圖像生成,書寫文稿,資訊搜尋等。随着 LLM 場景的多樣化,大家希望 LLM 能在垂直領域發揮其強大的功能。但是由于大模型在特定領域資料集的訓練和時效性限制,在 LLM 的基礎上建構垂直領域的産品時,需要将特定的知識庫輸入到大模型中來訓練或者推理。

目前常用的方式有兩種:微調(Fine-Tuning),提示學習(Prompt-Tuning)。前者是通過新資料集在已有模型上進一步訓練,訓練成本較高,時效性較差。後者在訓練成本,時效性上都比較靈活。

本文将基于提示學習方式,介紹如何基于火山引擎雲搜尋服務和方舟平台來建構專屬的智能問答系統。利用嵌入技術(embedding),通過嵌入模型,将資料集内容轉化為向量,然後借助火山引擎雲搜尋服務 ESCloud 的向量搜尋能力,将這些向量和資料儲存起來。在查詢階段,通過相似度查詢,比對出關聯的 topK 結果,然後将這些結果輔以提示詞提供給 LLM,最終生成相應的答案。這裡會從火山引擎方舟平台大模型廣場中選取一個大模型作為 LLM 來推理答案。選用開源架構 LangChain 作為建構端到端語言模型應用架構,簡化整個聊天模型的鍊路。

5分鐘,結合 LangChain 搭建自己的生成式智能問答系統

雲搜尋 VectorStore 準備

  1. 登入火山引擎雲搜尋服務,建立執行個體叢集,叢集版本選擇 7.10.
  2. 在火山引擎方舟平台大模型廣場選擇合适的模型,并檢視 API 調用說明
  3. 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. 依賴安裝
  2. pip install volcengine --user

    pip install langchain --user

  3. 初始化
#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 調用中看到樣例。

5分鐘,結合 LangChain 搭建自己的生成式智能問答系統
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**

5分鐘,結合 LangChain 搭建自己的生成式智能問答系統

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

調試可以看到提示詞:

5分鐘,結合 LangChain 搭建自己的生成式智能問答系統

回答:

5分鐘,結合 LangChain 搭建自己的生成式智能問答系統

以上就是基于火山引擎雲搜尋服務和方舟平台建構專屬智能問答系統的實踐,歡迎大家登陸火山引擎控制台操作!

雲搜尋服務 ESCloud 相容 Elasticsearch、Kibana 等軟體及常用開源插件,提供結構化、非結構化文本的多條件檢索、統計、報表,可以實作一鍵部署、彈性擴縮、簡化運維,快速建構日志分析、資訊檢索分析等業務能力。

繼續閱讀