自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

打造企業(yè)級智能問答系統(tǒng)的秘密:如何使用云數(shù)據(jù)庫 PostgreSQL 版實現(xiàn)向量檢索

數(shù)據(jù)庫
通過本文,你將會了解交互式問答系統(tǒng)的原理,學(xué)習(xí) PostgreSQL 的向量化存儲和檢索技術(shù),以及大語言模型交互技術(shù)等。

本文就如何利用火山引擎云數(shù)據(jù)庫 PostgreSQL 版和大語言模型技術(shù)(Large Language Model,簡稱 LLM),實現(xiàn)企業(yè)級智能交互式問答系統(tǒng)進行介紹。

背景

在大數(shù)據(jù)的浪潮下,眾多企業(yè)建立了自己的知識庫,以便于信息檢索和知識查詢。然而,隨著知識庫內(nèi)容的膨脹,傳統(tǒng)的信息檢索方式變得低效,經(jīng)常出現(xiàn)費時費力且結(jié)果不盡人意的情況。隨著生成式人工智能(AI Generated Content,簡稱 AIGC)的出現(xiàn),人們看到了一種更智能的實現(xiàn)方式,通過問答的方式,知識獲取的效率、準確性和用戶體驗在多方面得到提升。

即便如此,對于特定垂直領(lǐng)域的企業(yè),生成式人工智能的局限性也開始顯現(xiàn),例如大模型訓(xùn)練周期長、對某一領(lǐng)域?qū)I(yè)知識掌握不足等,這常常會導(dǎo)致 AI“幻覺”問題的出現(xiàn)(即 AI 的“一本正經(jīng)地胡說八道”)。為了解決這一難題,我們通常會采用以下兩種方式:

  • Fine Tune 方法,“馴服”大語言模型。
  • 利用領(lǐng)域知識,對大語言模型進行監(jiān)督微調(diào)(Supervised Fine Tune)和蒸餾(Distillation)。這種方式可塑性強,但需要大量的算力和人才資源,綜合成本高。此外,企業(yè)還需要持續(xù)監(jiān)控和更新模型,以確保與不斷變化的領(lǐng)域知識保持同步。
  • Prompt Engineering 方法,改變“自己”。
  • 該方法基于向量數(shù)據(jù)庫,補充足夠的對話上下文和參考資料,完善與大語言模型進行交互的問答問題(Prompt),其本質(zhì)是將大語言模型的推理歸納能力與向量化信息檢索能力相結(jié)合,從而快速建立能夠理解特定語境和邏輯的問答系統(tǒng)。該方法的實現(xiàn)成本相對較低。

接下來,本文針對 Prompt Engineering 方法,來演示將云數(shù)據(jù)庫 PostgreSQL 版作為向量數(shù)據(jù)庫的使用方法。

核心概念及原理

嵌入向量(Embedding Vectors)

向量 Embedding 是在自然語言處理和機器學(xué)習(xí)中廣泛使用的概念。各種文本、圖片或其他信號,均可通過一些算法轉(zhuǎn)換為向量化的 Embedding。在向量空間中,相似的詞語或信號距離更近,可以用這種性質(zhì)來表示詞語或信號之間的關(guān)系和相似性。例如,通過一定的向量化模型算法,將如下三句話,轉(zhuǎn)換成二維向量(x,y),我們可通過坐標系來畫出這些向量的位置,它們在二維坐標中的遠近,就顯示了其相似性,坐標位置越接近,其內(nèi)容就越相似。如下圖所示:

“今天天氣真好,我們出去放風(fēng)箏吧”
“今天天氣真好,我們出去散散步吧”
“這么大的雨,我們還是在家呆著吧”

圖片圖片

Prompt Engineering 過程原理

如上所說,使用者需要不斷調(diào)整輸入提示,從而獲得相關(guān)領(lǐng)域的專業(yè)回答。輸入模型的相關(guān)提示內(nèi)容越接近問題本身,模型的輸出越趨近于專業(yè)水平。通俗理解就是,模型能夠利用所輸入的提示信息,從中抽取出問題的答案,并總結(jié)出一份專業(yè)水準的回答。整個 Prompt Engineering 工作流程如下圖所示:

圖片圖片

其大致可以分為兩個階段:向量構(gòu)建階段和問答階段。在向量構(gòu)建階段,將企業(yè)知識庫的所有文檔,分割成內(nèi)容大小適當?shù)钠?,然后通過 Embeddings 轉(zhuǎn)換算法,例如 OpenAI 的模型 API(https://platform.openai.com/docs/guides/embeddings/what-are-embeddings),將其轉(zhuǎn)換成 Embeddings 數(shù)據(jù),存儲于云數(shù)據(jù)庫 PostgreSQL 版向量數(shù)據(jù)庫中,詳細流程如下圖所示:

圖片圖片

在問答階段,問答系統(tǒng)首先接收用戶的提問,并將其轉(zhuǎn)化為 Embedding 數(shù)據(jù),然后通過與向量化的問題進行相似性檢索,獲取最相關(guān)的 TOP N 的知識單元。接著,通過 Prompt 模板將問題、最相關(guān)的 TOP N 知識單元、歷史聊天記錄整合成新的問題。大語言模型將理解并優(yōu)化這個問題,然后返回相關(guān)結(jié)果。最后,系統(tǒng)將結(jié)果返回給提問者。流程如下圖所示:

圖片圖片

實現(xiàn)過程

接下來將介紹如何利用云數(shù)據(jù)庫 PostgreSQL 版提供的 pg_vector 插件構(gòu)建用于向量高效存儲、檢索的向量數(shù)據(jù)庫。

前置條件

  • 已創(chuàng)建 ECS 實例,或者使用本地具備 Linux 環(huán)境的主機,作為訪問數(shù)據(jù)庫的客戶端機器。
  • 請確保您具備 OpenAI Secret API Key,并且您的網(wǎng)絡(luò)環(huán)境可以使用 OpenAI。

訓(xùn)練步驟

本文將以構(gòu)建企業(yè)專屬“數(shù)據(jù)庫顧問”問答系統(tǒng)為例,演示整個構(gòu)建過程。使用的知識庫樣例為https://www.postgresql.org/docs/15/index.html,腳本獲取方式詳見文末。

搭建的環(huán)境基于 Debian 9.13,以下方案僅供參考,環(huán)境不同依賴包安裝有所差異。

以下過程包括兩個主要腳本文件,構(gòu)建知識庫的 generate-embeddings.ts,問答腳本 queryGPT.py,建議組織項目目錄如下所示:

.
├── package.json                              // ts依賴包
├── docs
│   ├── PostgreSQL15.mdx                      // 知識庫文檔
├── script
│   ├── generate-embeddings.ts                // 構(gòu)建知識庫
│   ├── queryGPT.py                           // 問答腳本

1. 學(xué)習(xí)階段

1. 創(chuàng)建 PostgreSQL 實例

登錄云數(shù)據(jù)庫 PostgreSQL 版控制臺(https://console.volcengine.com/db/rds-pg)創(chuàng)建實例,并創(chuàng)建數(shù)據(jù)庫和賬號。關(guān)于創(chuàng)建 PostgreSQL 實例、數(shù)據(jù)庫、賬號的詳細信息,請參見云數(shù)據(jù)庫 PostgreSQL 版快速入門(https://www.volcengine.com/docs/6438/79234)。

2. 創(chuàng)建插件

進入測試數(shù)據(jù)庫,并創(chuàng)建 pg_vector 插件。

create extension if not exists vector;

創(chuàng)建對應(yīng)的數(shù)據(jù)庫表,其中表 doc_chunks 中的字段 embedding 即為表示知識片段的向量。

-- 記錄文檔信息
create table docs (
  id bigserial primary key,
  -- 父文檔ID
  parent_doc bigint references docs,
  -- 文檔路徑
  path text not null unique,
  -- 文檔校驗值
  checksum text
);
-- 記錄chunk信息
create table doc_chunks (
  id bigserial primary key,
  doc_id bigint not null references docs on delete cascade, -- 文檔ID
  content text, -- chunk內(nèi)容
  token_count int, -- chunk中的token數(shù)量
  embedding vector(1536), -- chunk轉(zhuǎn)化成的embedding向量
  slug text, -- 為標題生成唯一標志
  heading text -- 標題
);

3. 構(gòu)建向量知識庫

在客戶端機器上,將知識庫文檔內(nèi)容,分割成內(nèi)容大小適當?shù)钠危ㄟ^ OpenAI 的 embedding 轉(zhuǎn)化接口,轉(zhuǎn)化成embedding 向量,并存儲到數(shù)據(jù)庫,參考腳本獲取方式詳見文末。

注意 該腳本只能處理 markdown 格式的文件。

安裝 pnpm:

curl -fsSL https://get.pnpm.io/install.sh | sh -

安裝 nodejs(參考https://github.com/nodesource/distributions):

sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=16
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
sudo apt-get update
sudo apt-get install nodejs -y

安裝 typescript 依賴,配置文件 package.json 獲取方式詳見文末:

pnpm run setup
pnpm install tsx

修改 generate-embeddings.ts,設(shè)置 OpenAI 的 key、PG 的連接串以及 markdown 文檔目錄:

#這里需要將user、passwd、127.0.0.1、5432 替換為實際數(shù)據(jù)庫用戶、密碼、數(shù)據(jù)庫地址、端口
const postgresql_url = 'pg://user:passwd@127.0.0.1:5432/database';
const openai_key = '-------------';
const SOURCE_DIR = path.join(__dirname, 'document path');

運行腳本,生成文檔 embedding 向量并插入數(shù)據(jù)庫:

pnpm tsx script/generate-embeddings.ts

運行過程:

圖片圖片

腳本運行后,我們查看下所構(gòu)建的知識庫。查詢 docs 表:

圖片圖片

查詢 docs_chunk 表,批量導(dǎo)入向量成功:

圖片圖片

2. 問答階段

1. 創(chuàng)建相似度計算函數(shù)

為了方便應(yīng)用使用,使用 PostgreSQL 的自定義函數(shù)功能,創(chuàng)建內(nèi)置于數(shù)據(jù)庫內(nèi)的函數(shù)。應(yīng)用只需調(diào)用 PostgreSQL,該函數(shù)便可在應(yīng)用程序中獲取向量匹配結(jié)果。示例中使用“內(nèi)積”來計算向量的相似性。

create or replace function match_chunks(chunck_embedding vector(1536), threshold float, count int, min_length int)
returns table (id bigint, content text, similarity float)
language plpgsql
as $$
begin
  return query
  select
    doc_chunks.id,
    doc_chunks.content,
    (doc_chunks.embedding <#> chunck_embedding) * -1 as similarity
  from doc_chunks

  -- chunk內(nèi)容大于設(shè)定的長度
  where length(doc_chunks.content) >= min_length

  -- The dot product is negative because of a Postgres limitation, so we negate it
  and (doc_chunks.embedding <#> chunck_embedding) * -1 > threshold
  order by doc_chunks.embedding <#> chunck_embedding
  
  limit count;
end;
$$;

2. 提問及回答

以下 Python 程序,可以接收提問者問題,并實現(xiàn)上述 Prompt Engineering 的“問答階段”的功能,最終將具備“邏輯思考”+“深度領(lǐng)域知識”的解答,發(fā)送給提問者。

import os, psycopg2, openai
def query_handler(query = None):
    if query is None or query == "":
        print('請輸入有效問題')
        return
    query = query.strip().replace('\n', ' ')
    embedding = None
    try:
        # 使用 GPT 將提問轉(zhuǎn)化為 embedding 向量
        response = openai.Embedding.create(
            engine="text-embedding-ada-002",  # 固定為text-embedding-ada-002
            input=[query],
        )
        embedding = response.data[0].embedding
    except Exception as ex:
        print(ex)
        return
    content = ""
    con = None
    try:
        # 處理 postgres 配置,連接數(shù)據(jù)庫
        # host:127.0.0.1,port:5432,user:test,password:test,database:test
        params = postgresql_url.split(',')
        database, user, password, host, port = "test", "test", "test", "127.0.0.1", "5432"
        for param in params:
            pair = param.split(':')
            if len(pair) != 2:
                print('POSTGRESQL_URL error: ' + postgresql_url)
                return
            k, v = pair[0].strip(), pair[1].strip()
            if k == 'database':
                database = v
            elif k == 'user':
                user = v
            elif k == 'password':
                password = v
            elif k == 'host':
                host = v
            elif k == 'port':
                port = v
        # connect postgres
        con = psycopg2.connect(database=database, user=user, password=password, host=host, port=port)
        cur = con.cursor()
        # 從數(shù)據(jù)庫查詢?nèi)舾蓷l最接近提問的 chunk
        sql = "select match_chunks('[" + ','.join([str(x) for x in embedding]) + "]', 0.78, 5, 50)"
        cur.execute(sql)
        rows = cur.fetchall()
        for row in rows:
            row = row[0][1:-2].split(',')[-2][1:-2].strip()
            content = content + row + "\n---\n"
    except Exception as ex:
        print(ex)
        return
    finally:
        if con is not None:
            con.close()
    try:
        # 組織提問和 chunk 內(nèi)容,發(fā)送給 GPT
        prompt = '''Pretend you are GPT-4 model , Act an database expert.
        I will introduce a database scenario for which you will provide advice and related sql commands.
        Please only provide advice related to this scenario. Based on the specific scenario from the documentation,
        answer the question only using that information. Please note that if there are any updates to the database
        syntax or usage rules, the latest content shall prevail. If you are uncertain or the answer is not explicitly
        written in the documentation, please respond with "I'm sorry, I cannot assist with this.\n\n''' + "Context sections:\n" + \
        content.strip().replace('\n', ' ') + "\n\nQuestion:"""" + query.replace('\n', ' ') + """"\n\nAnswer:"
        print('\n正在處理,請稍后。。。\n')
        response = openai.ChatCompletion.create(
            engine="gpt_openapi",  # 固定為gpt_openapi
            messages=[
                {"role": "user", "content": prompt}
            ],
            model="gpt-35-turbo",
            temperature=0,
        )
        print('回答:')
        print(response['choices'][0]['message']['content'])

    except Exception as ex:
        print(ex)
        return
os.environ['OPENAI_KEY'] = '-----------------------'
os.environ['POSTGRESQL_URL'] = 'host:127.0.0.1,port:5432,user:test,password:test,database:test'
openai_key = os.getenv('OPENAI_KEY')
postgresql_url = os.getenv('POSTGRESQL_URL')
# openai config
openai.api_type = "azure"
openai.api_base = "https://example-endpoint.openai.azure.com"
openai.api_version = "2023-XX"
openai.api_key = openai_key
def main():
    if openai_key is None or postgresql_url is None:
        print('Missing environment variable OPENAI_KEY, POSTGRESQL_URL(host:127.XX.XX.XX,port:5432,user:XX,password:XX,database:XX)')
        return
    print('我是您的PostgreSQL AI助手,請輸入您想查詢的問題,例如:\n1、如何創(chuàng)建table?\n2、給我解釋一下select語句?\n3、如何創(chuàng)建一個存儲過程?')
    while True:
        query = input("\n輸入您的問題:")
        query_handler(query)
if __name__ == "__main__":
    main()

先修改 90、91 行的 OpenAI 的 key 和 PG 的連接串,為實際 key 和連接地址:

os.environ['OPENAI_KEY'] = '-----------------------'
os.environ['POSTGRESQL_URL'] = 'host:127.0.0.1,port:5432,user:test,password:test,database:test'

然后修改 GPT 的參數(shù):

openai.api_type = "azure"
openai.api_base = "https://example-endpoint.openai.azure.com"
openai.api_version = "2023-XX"

其次通過修改機器人自我介紹,以讓提問者快速了解問答機器人的專業(yè)特長,這里的自我介紹,說明機器人是一個數(shù)據(jù)庫專家的角色。

prompt = '''Pretend you are GPT-4 model , Act an database expert.
        I will introduce a database scenario for which you will provide advice and related sql commands.
        Please only provide advice related to this scenario. Based on the specific scenario from the documentation,
        answer the question only using that information. Please note that if there are any updates to the database
        syntax or usage rules, the latest content shall prevail. If you are uncertain or the answer is not explicitly
        written in the documentation, please respond with "I'm sorry, I cannot assist with this.\n\n''' + "Context sections:\n" + \
        content.strip().replace('\n', ' ') + "\n\nQuestion:"""" + query.replace('\n', ' ') + """"\n\nAnswer:"

最后安裝腳本依賴:

pip install psycopg2-binary
pip install openai
pip install 'openai[datalib]'

測試過程:

圖片圖片

到此為止,您就獲得了一個企業(yè)級專屬智能問答系統(tǒng)。

方案優(yōu)勢

相較于其他向量數(shù)據(jù)庫,借助火山引擎云數(shù)據(jù)庫 PostgreSQL 版提供的 pg_vector 插件構(gòu)建的向量數(shù)據(jù)庫具有如下優(yōu)勢:

  • 使用便捷易上手: 無需專業(yè) AI 專家介入,無需構(gòu)建其他大規(guī)模復(fù)雜分布式集群,只需要一個數(shù)據(jù)庫實例,便可構(gòu)建專用向量數(shù)據(jù)庫。使用接口兼容現(xiàn)有 SQL 語法,不需要定制化調(diào)度框架、終端。
  • 性價比高: 可使用已有數(shù)據(jù)庫實例,不需要額外購買其他龐大的集群資源。
  • 數(shù)據(jù)實時更新可用: 向量數(shù)據(jù)可以在毫秒級實現(xiàn)新增、更新,并且依然具備事務(wù)屬性,無需擔(dān)心數(shù)據(jù)的錯亂。
  • 支持高并發(fā),擴展容易: 在向量化場景可支持數(shù)千 TPS;在性能出現(xiàn)瓶頸時,可以通過一鍵擴展只讀節(jié)點,輕松實現(xiàn)整體吞吐的瞬間提升。
  • 支持向量維度高: pg_vector 還具備支持向量維度高的特點。最多可支持 16000 維向量,能夠滿足絕大部分向量化存儲、使用場景。

責(zé)任編輯:龐桂玉 來源: 字節(jié)跳動技術(shù)團隊
相關(guān)推薦

2018-06-07 08:20:51

自動化測試移動技術(shù)云平臺

2024-08-02 13:31:47

企業(yè)級智能應(yīng)用

2019-07-29 09:37:44

海量數(shù)據(jù)企業(yè)級私有云

2018-07-30 16:34:50

智能

2020-03-11 09:50:21

時序數(shù)據(jù)庫快速檢索

2016-12-14 14:00:53

2016-10-21 17:17:06

2013-12-03 11:00:48

2017-03-29 13:24:32

騰訊云靈雀云

2015-10-27 12:17:15

靈雀云容器Docker

2024-12-09 08:39:31

PostgreSQL數(shù)據(jù)庫企業(yè)級

2019-10-10 09:55:52

數(shù)據(jù)庫安全數(shù)據(jù)庫網(wǎng)絡(luò)安全

2016-04-20 21:06:02

阿里云云棲大會企業(yè)級

2021-04-08 15:16:50

OPEN

2018-09-27 14:30:13

阿里云數(shù)據(jù)庫MariaDB

2017-04-07 08:46:30

數(shù)據(jù)庫云計算青云

2018-12-10 12:08:14

聯(lián)想

2013-10-18 11:01:30

OpenStack云計算開源

2020-12-24 18:18:33

騰訊云數(shù)據(jù)庫分布式
點贊
收藏

51CTO技術(shù)棧公眾號