本教程演示如何使用向量檢索服務(DashVector),結合LLM大模型等能力,來打造基於垂直領域專屬知識等問答服務。其中LLM大模型能力,以及文字向量生成等能力,這裡基於靈積模型服務上的通義千問 API以及Embedding API來接入。
背景及實現思路
大語言模型(LLM)作為自然語言處理領域的核心技術,具有豐富的自然語言處理能力。但其訓練語料庫具有一定的侷限性,一般由普適知識、常識性知識,如維基百科、新聞、小說,和各種領域的專業知識組成。導致 LLM 在處理特定領域的知識表示和應用時存在一定的侷限性,特別對於垂直領域內,或者企業內部等私域專屬知識。
實現專屬領域的知識問答的關鍵,在於如何讓LLM能夠理解並獲取存在於其訓練知識範圍外的特定領域知識。同時可以透過特定Prompt構造,提示LLM在回答特定領域問題的時候,理解意圖並根據注入的領域知識來做出回答。在通常情況下,使用者的提問是完整的句子,而不像搜尋引擎只輸入幾個關鍵字。這種情況下,直接使用關鍵字與企業知識庫進行匹配的效果往往不太理想,同時長句本身還涉及分詞、權重等處理。相比之下,倘若我們把提問的文字,和知識庫的內容,都先轉化為高質量向量,再透過向量檢索將匹配過程轉化為語義搜尋,那麼提取相關知識點就會變得簡單而高效。
接下來我們將基於中文突發事件語料庫(CEC Corpus)演示關於突發事件新聞報導的知識問答。
整體流程
主要分為三個階段:
本地知識庫的向量化。透過文字向量模型將其轉化為高質量低維度的向量資料,再寫入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 新聞資料集裡,有如下一篇報導。因為整個新聞資料集已經在之前的步驟裡,轉換成向量入庫了,我們現在就可以把這個新聞報導作為一個知識點,做出針對性提問:海南安定追尾事故,發生在哪裡?原因是什麼?人員傷亡情況如何?,並檢視相應答案。
建立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}')
可以看到,基於DashVector作為向量檢索的底座,LLM大模型的知識範疇得到了針對性的擴充套件,並且能夠對於專屬的特定知識領域做出正確的回答。
寫在最後
從本文的範例中,可以看到DashVector作為一個獨立的向量檢索服務,提供了開箱即用的強大向量檢索服務能力,這些能力和各個AI模型結合,能夠衍生多樣的AI應用的可能。這裡的範例中,LLM大模型問答,以及文字向量生成等能力,都是基於靈積模型服務上的通義千問API和Embedding API來接入的,在實際操作中,相關能力同樣可以透過其他三方服務,或者開源模型社群,比如ModelScope上的各種開源LLM模型來實現。
免費體驗阿里雲高效能向量檢索服務:https://www.aliyun.com/product/ai/dashvector