基於 EventBridge + DashVector 打造 RAG 全鏈路動態語義檢索能力

阿里云云原生發表於2024-11-05

作者:肯夢

本文將演示如何使用事件匯流排(EventBridge),向量檢索服務(DashVector),函式計算(FunctionCompute)結合靈積模型服務 [ 1] 上的 Embedding API [ 2] ,來從 0 到 1 構建基於文字索引的構建+向量檢索基礎上的語義搜尋能力。具體來說,我們將基於 OSS 文字文件動態插入資料,進行實時的文字語義搜尋,查詢最相似的相關內容。

本文中將用到事件匯流排(EventBridge),它是阿里雲提供的一款無伺服器事件匯流排服務,支援阿里雲服務、自定義應用、SaaS 應用以標準化、中心化的方式接入,並能夠以標準化的 CloudEvents 1.0 協議在這些應用之間路由事件,幫助您輕鬆構建松耦合、分散式的事件驅動架構。

RAG 背景概述

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

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

本文將介紹如何構建一個完全動態的 RAG 入庫方案,透過 EventBridge 拉取 OSS 非結構化資料,同時將資料投遞至 DashVector 向量資料庫,從而實現完整的 RAG Ingestion 流程。

流程概述

資料整合(Ingestion)

資料檢索(Search)

操作流程

前提條件

  • DashScope 控制檯開通靈積模型服務,並獲得 API-KEY 的獲取與配置。
  • 開通 DashVector 向量檢索服務,並獲得 API-KEY 的獲取與配置。
  • 開通 OSS 服務。
  • 開通 FC 服務。
  • 開通 EventBridge 服務。

開通靈積模型服務

  1. 點選進入 DashScope 控制檯 [ 3] ,開通靈積相關服務

  1. 點選進入“API-KEY”管理,獲取相關 KEY 資訊

開通 DashVector 服務

  1. 若第一次配置,請點選“新建 DashVector Cluster [ 4] ”,跳轉建立新的 Cluster;點選“建立免費 Cluster”快速體驗建立向量資料庫

2. 選擇“立即購買”

3. 點選建立“Collection”

4. 填寫緯度為“1536”,距離度量方式“Cosine”,點選“確認”

5. 點選“API-KEY 管理”,獲取 DashVector 的 API KEY

建立 Ingestion 資料整合任務

1.1 進入 EventBridge 控制檯 [ 5]

1.2 配置 OSS 源

  • OSS Bucket:選擇空白儲存桶實驗,若無請自行建立;
  • OSS 字首:該項可根據訴求填寫,若無字首 EB 將拉取整個 Bucket 內容;本次演示不配置;
  • 文件載入:目前支援解析 TextLoder 作為文件載入器;
  • 載入模式:“單文件載入”單個檔案作為一條資料載入,“分塊載入”按照分隔符載入資料;本次演示使用單文件載入。

1.3 配置過濾

可根據訴求新增過濾規則,本次演示使用“匹配全部事件”。

1.4 配置轉換

轉換部分主要是將原始資料轉成向量化資料,為投遞至 DashVector 做資料準備。

函式程式碼如下,函式環境為 Python 3.10:

# -*- coding: utf-8 -*-
import os
import ast
import copy
import json
import logging
import dashscope
from dashscope import TextEmbedding
from http import HTTPStatus

logger = logging.getLogger()
logger.setLevel(level=logging.INFO)

dashscope.api_key='Your-API-KEY'

def handler(event, context):
  evt = json.loads(event)
  evtinput = evt['data']
  resp = dashscope.TextEmbedding.call(
        model=dashscope.TextEmbedding.Models.text_embedding_v1,
        api_key=os.getenv('DASHSCOPE_API_KEY'), 
        input= evtinput )
  if resp.status_code == HTTPStatus.OK:
        print(resp)
  else:
        print(resp)
  return resp

🔔 注意: 需手動安裝相關函式環境,相關文件參考《為函式安裝第三方依賴》 [ 6]

pip3 install dashvector dashscope -t .

返回樣例:

{
    "code": "",
    "message": "",
    "output": {
        "embeddings": [
            {
                "embedding": [
                    -2.192838430404663,
                    -0.703125,
                    ... ...
                    -0.8980143070220947,
                    -0.9130208492279053,
                    -0.520526111125946,
                    -0.47154948115348816
                ],
                "text_index": 0
            }
        ]
    },
    "request_id": "e9f9a555-85f2-9d15-ada8-133af54352b8",
    "status_code": 200,
    "usage": {
        "total_tokens": 3
    }
}

1.5 配置向量資料庫 Dashvector

選擇建立好的向量資料庫。

  • 資料對映:選擇 Upsert 方式插入;
  • 向量:填寫上游 Dashscope 的 TextEmbedding 投遞的向量資訊 $.output. embeddings[0].embedding;
  • 鑑權配置:獲取的 DashVector API-KEY 引數。

建立 Search 資料檢索任務

在進行資料檢索時,需要首先對資料進行 embedding,然後將 embedding 後的向量值與資料庫值做檢索排序。最後填寫 prompt 模版,透過自然語言理解和語義分析,理解資料檢索意圖。

該任務可以部署在雲端函式計算,或者直接在本地環境執行;首先,我們建立 embedding.py,將需要檢索的問題進行文字向量化,程式碼如下所示:

embedding.py

import os
import dashscope
from dashscope import TextEmbedding

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}'

然後,建立 search.py 檔案,並將如下示例程式碼複製到 search.py 檔案中,透過 DashVector 的向量檢索能力來檢索相似度的最高的內容。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']

建立 answer.py 檔案,我們就可以按照特定的模板作為 prompt 向 LLM 發起提問了,在這裡我們選用的 LLM 是通義千問(qwen-turbo),程式碼示例如下:

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

最後,建立 run.py 檔案,並將如下示例程式碼複製到 run.py 檔案中,並最終執行 run.py 檔案。(驗證時,可在繫結的 OSS Bucket 上傳需要被檢索的知識庫資訊。)

import dashscope

from search import search_relevant_news
from answer import answer_question

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

    question = 'EventBridge 是什麼,它有哪些能力?'
    context = search_relevant_news(question)
    answer = answer_question(question, context)

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

總結

從本文的範例中,我們可以比較方便的使用 EventBridge 提供的 OSS To DashVector 離線資料流匯入能力,開箱即用的構建強大向量檢索服務能力,這些能力和各個 AI 模型結合,能夠衍生多樣的 AI 應用的可能。同樣,Transform 部分使用了函式計算能力,可以更靈活的制定想要的 Split 切分演算法,提供更靈活且具備生產力的 RAG 方案。

相關連結:

[1] 靈積模型服務

https://dashscope.aliyun.com/

[2] Embedding API

https://help.aliyun.com/zh/dashscope/developer-reference/text...

[3] DashScope 控制檯

https://account.aliyun.com/login/login.htm?oauth_callback=htt...

[4] 新建 DashVector Cluster

https://account.aliyun.com/login/login.htm?oauth_callback=htt...

[5] EventBridge 控制檯

https://account.aliyun.com/login/login.htm?oauth_callback=htt...

[6] 《為函式安裝第三方依賴》

https://help.aliyun.com/zh/functioncompute/fc-3-0/user-guide/...

相關文章