DashVector x 通義千問大模型:打造基於專屬知識的問答服務

DashVector發表於2024-05-17

本教程演示如何使用向量檢索服務(DashVector,結合LLM大模型等能力,來打造基於垂直領域專屬知識等問答服務。其中LLM大模型能力,以及文字向量生成等能力,這裡基於靈積模型服務上的通義千問 API以及Embedding API來接入。

背景及實現思路

大語言模型(LLM)作為自然語言處理領域的核心技術,具有豐富的自然語言處理能力。但其訓練語料庫具有一定的侷限性,一般由普適知識、常識性知識,如維基百科、新聞、小說,和各種領域的專業知識組成。導致 LLM 在處理特定領域的知識表示和應用時存在一定的侷限性,特別對於垂直領域內,或者企業內部等私域專屬知識。

實現專屬領域的知識問答的關鍵,在於如何讓LLM能夠理解並獲取存在於其訓練知識範圍外的特定領域知識。同時可以透過特定Prompt構造,提示LLM在回答特定領域問題的時候,理解意圖並根據注入的領域知識來做出回答。在通常情況下,使用者的提問是完整的句子,而不像搜尋引擎只輸入幾個關鍵字。這種情況下,直接使用關鍵字與企業知識庫進行匹配的效果往往不太理想,同時長句本身還涉及分詞、權重等處理。相比之下,倘若我們把提問的文字,和知識庫的內容,都先轉化為高質量向量,再透過向量檢索將匹配過程轉化為語義搜尋,那麼提取相關知識點就會變得簡單而高效。

接下來我們將基於中文突發事件語料庫(CEC Corpus)演示關於突發事件新聞報導的知識問答。

整體流程

image
主要分為三個階段:

本地知識庫的向量化。透過文字向量模型將其轉化為高質量低維度的向量資料,再寫入DashVector向量檢索服務。這裡資料的向量化我們採用了靈積模型服務上的Embedding API實現。

相關知識點的提取。將提問文字向量化後,透過 DashVector 提取相關知識點的原文。

構造 Prompt 進行提問。將相關知識點作為“限定上下文+提問” 一起作為prompt詢問通義千問。

前提準備

1. API-KEY 和 Cluster準備
開通靈積模型服務,並獲得 API-KEY。請參考:開通DashScope並建立API-KEY。

開通DashVector向量檢索服務,並獲得 API-KEY。請參考:DashVector API-KEY管理。

開通DashVector向量檢索服務,並建立Cluster。

獲取Cluster的Endpoint,Endpoint獲取請檢視 Cluster詳情。

說明
靈積模型服務DashScope的API-KEY與DashVector的API-KEY是獨立的,需要分開獲取。

2. 環境準備
說明
需要提前安裝 Python3.7 及以上版本,請確保相應的 python 版本。
pip3 install dashvector dashscope
3. 資料準備
git clone https://github.com/shijiebei2009/CEC-Corpus.git

搭建步驟

說明
本教程所涉及的 your-xxx-api-key 以及 your-xxx-cluster-endpoint,均需要替換為您自己的API-KAY及CLUSTER_ENDPOINT後,程式碼才能正常執行。

1. 本地知識庫的向量化
CEC-Corpus 資料集包含 332 篇突發事件的新聞報導的語料和標註資料,這裡我們只需要提取原始的新聞稿文字,並將其向量化後入庫。文字向量化的教程可以參考《基於向量檢索服務與靈積實現語義搜尋》。建立embedding.py檔案,並將如下示例程式碼複製到embedding.py中:

點選檢視程式碼
import os

import dashscope
from dashscope import TextEmbedding

from dashvector import Client, Doc


def prepare_data(path, batch_size=25):
    batch_docs = []
    for file in os.listdir(path):
        with open(path + '/' + file, 'r', encoding='utf-8') as f:
            batch_docs.append(f.read())
            if len(batch_docs) == batch_size:
                yield batch_docs
                batch_docs = []

    if batch_docs:
        yield batch_docs


def generate_embeddings(news):
    rsp = TextEmbedding.call(
        model=TextEmbedding.Models.text_embedding_v1,
        input=news
    )
    embeddings = [record['embedding'] for record in rsp.output['embeddings']]
    return embeddings if isinstance(news, list) else embeddings[0]


if __name__ == '__main__':
    dashscope.api_key = '{your-dashscope-api-key}'
    
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 建立集合:指定集合名稱和向量維度, text_embedding_v1 模型產生的向量統一為 1536 維
    rsp = client.create('news_embedings', 1536)
    assert rsp

    # 載入語料
    id = 0
    collection = client.get('news_embedings')
    for news in list(prepare_data('CEC-Corpus/raw corpus/allSourceText')):
        ids = [id + i for i, _ in enumerate(news)]
        id += len(news)
        
        vectors = generate_embeddings(news)
        # 寫入 dashvector 構建索引
        rsp = collection.upsert(
            [
                Doc(id=str(id), vector=vector, fields={"raw": doc})
                for id, vector, doc in zip(ids, vectors, news)
            ]
        )
        assert rsp

在示例中,我們將 Embedding 向量和新聞報導的文稿(作為raw欄位)一起存入DashVector向量檢索服務中,以便向量檢索時召回原始文稿。

2. 知識點的提取
將 CEC-Corpus 資料集所有新聞報導寫入DashVector服務後,就可以進行快速的向量檢索。實現這個檢索,我們同樣將提問的問題進行文字向量化後,再在DashVector服務中檢索最相關的知識點,也就是相關新聞報導。建立search.py檔案,並將如下示例程式碼複製到search.py檔案中。

點選檢視程式碼
from dashvector import Client

from embedding import generate_embeddings


def search_relevant_news(question):
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 獲取剛剛存入的集合
    collection = client.get('news_embedings')
    assert collection

    # 向量檢索:指定 topk = 1 
    rsp = collection.query(generate_embeddings(question), output_fields=['raw'],
                           topk=1)
    assert rsp
    return rsp.output[0].fields['raw']

3. 構造 Prompt 向LLM(通義千問)提問
在透過提問搜尋到相關的知識點後,我們就可以將 “提問 + 知識點” 按照特定的模板作為 prompt 向LLM發起提問了。在這裡我們選用的LLM是通義千問,這是阿里巴巴自主研發的超大規模語言模型,能夠在使用者自然語言輸入的基礎上,透過自然語言理解和語義分析,理解使用者意圖。可以透過提供儘可能清晰詳細的指令(prompt),來獲取更符合預期的結果。這些能力都可以透過通義千問API來獲得。

具體我們這裡設計的提問模板格式為:請基於我提供的內容回答問題。內容是{},我的問題是{},當然您也可以自行設計合適的模板。建立answer.py,並將如下示例程式碼複製到answer.py中。

點選檢視程式碼
from dashscope import Generation


def answer_question(question, context):
    prompt = f'''請基於```內的內容回答問題。"
	```
	{context}
	```
	我的問題是:{question}。
    '''
    
    rsp = Generation.call(model='qwen-turbo', prompt=prompt)
    return rsp.output.text

知識問答

做好這些準備工作以後,就可以對LLM做與具體知識點相關的提問了。比如在 CEC-Corpus 新聞資料集裡,有如下一篇報導。因為整個新聞資料集已經在之前的步驟裡,轉換成向量入庫了,我們現在就可以把這個新聞報導作為一個知識點,做出針對性提問:海南安定追尾事故,發生在哪裡?原因是什麼?人員傷亡情況如何?,並檢視相應答案。
image
建立run.py檔案,並將如下示例程式碼複製到run.py檔案中。

點選檢視程式碼
import dashscope

from search import search_relevant_news
from answer import answer_question

if __name__ == '__main__':
    dashscope.api_key = '{your-dashscope-api-key}'

    question = '海南安定追尾事故,發生在哪裡?原因是什麼?人員傷亡情況如何?'
    context = search_relevant_news(question)
    answer = answer_question(question, context)

    print(f'question: {question}\n' f'answer: {answer}')

image

可以看到,基於DashVector作為向量檢索的底座,LLM大模型的知識範疇得到了針對性的擴充套件,並且能夠對於專屬的特定知識領域做出正確的回答。

寫在最後

從本文的範例中,可以看到DashVector作為一個獨立的向量檢索服務,提供了開箱即用的強大向量檢索服務能力,這些能力和各個AI模型結合,能夠衍生多樣的AI應用的可能。這裡的範例中,LLM大模型問答,以及文字向量生成等能力,都是基於靈積模型服務上的通義千問API和Embedding API來接入的,在實際操作中,相關能力同樣可以透過其他三方服務,或者開源模型社群,比如ModelScope上的各種開源LLM模型來實現。


免費體驗阿里雲高效能向量檢索服務:https://www.aliyun.com/product/ai/dashvector
image

相關文章