如何實(shí)現(xiàn)AI的矢量數(shù)據(jù)庫(kù)
推薦:使用NSDT場(chǎng)景編輯器助你快速搭建3D應(yīng)用場(chǎng)景
然而,人工智能模型有點(diǎn)像美食廚師。他們可以創(chuàng)造奇跡,但他們需要優(yōu)質(zhì)的成分。人工智能模型在大多數(shù)輸入上都做得很好,但如果它們以最優(yōu)化的格式接收輸入,它們就會(huì)真正發(fā)光。這就是矢量數(shù)據(jù)庫(kù)的重點(diǎn)。
在本文的過程中,我們將深入探討什么是矢量數(shù)據(jù)庫(kù),為什么它們?cè)谌斯ぶ悄苁澜缰凶兊迷絹?lái)越重要,然后我們將查看實(shí)現(xiàn)矢量數(shù)據(jù)庫(kù)的分步指南。
跳躍前進(jìn):
什么是矢量數(shù)據(jù)庫(kù)?
為什么需要矢量數(shù)據(jù)庫(kù)?
實(shí)現(xiàn)矢量數(shù)據(jù)庫(kù):分步指南
先決條件
設(shè)置Weaviate項(xiàng)目
創(chuàng)建我們的節(jié)點(diǎn).js項(xiàng)目
設(shè)置我們的矢量數(shù)據(jù)庫(kù)
設(shè)置客戶端
遷移數(shù)據(jù)
添加文檔
刪除文檔
向數(shù)據(jù)庫(kù)添加查詢函數(shù)
結(jié)合向量嵌入和 AI
人工智能模型設(shè)置
查詢我們的數(shù)據(jù)
測(cè)試我們的查詢
在我們開始探索矢量數(shù)據(jù)庫(kù)之前,了解在編程和機(jī)器學(xué)習(xí)的上下文中什么是矢量非常重要。
在編程中,向量本質(zhì)上是一個(gè)一維數(shù)字?jǐn)?shù)組。如果您曾經(jīng)編寫過涉及 3D 圖形或機(jī)器學(xué)習(xí)算法的代碼,那么您很可能使用過向量。
const vector4_example = [0.5, 1.5, 6.0, 3.4]
它們只是數(shù)字?jǐn)?shù)組,通常是浮點(diǎn)數(shù),我們用它們的維度來(lái)指代。例如,a 是浮點(diǎn)數(shù)的三元素?cái)?shù)組,a 是浮點(diǎn)數(shù)的四元素?cái)?shù)組。就這么簡(jiǎn)單!vector3vector4
但向量不僅僅是數(shù)字?jǐn)?shù)組。在機(jī)器學(xué)習(xí)的背景下,向量在高維空間中表示和操作數(shù)據(jù)方面發(fā)揮著關(guān)鍵作用。這使我們能夠執(zhí)行驅(qū)動(dòng)AI模型的復(fù)雜操作和計(jì)算。
現(xiàn)在我們已經(jīng)掌握了向量,讓我們把注意力轉(zhuǎn)向向量數(shù)據(jù)庫(kù)。
乍一看,你可能會(huì)想,“嘿,既然向量只是數(shù)字?jǐn)?shù)組,我們不能使用常規(guī)數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)它們嗎?好吧,從技術(shù)上講,你可以。但這就是事情變得有趣的地方。
矢量數(shù)據(jù)庫(kù)是一種特殊類型的數(shù)據(jù)庫(kù),針對(duì)存儲(chǔ)和執(zhí)行對(duì)大量矢量數(shù)據(jù)的操作進(jìn)行了優(yōu)化。因此,雖然您的常規(guī)數(shù)據(jù)庫(kù)確實(shí)可以存儲(chǔ)數(shù)組,但矢量數(shù)據(jù)庫(kù)更進(jìn)一步,提供了專門的工具和操作來(lái)處理矢量。
在下一節(jié)中,我們將討論為什么矢量數(shù)據(jù)庫(kù)是必要的,以及它們帶來(lái)的優(yōu)勢(shì)。所以堅(jiān)持下去,因?yàn)槭虑闀?huì)變得更加有趣!
為什么需要矢量數(shù)據(jù)庫(kù)?現(xiàn)在我們已經(jīng)對(duì)什么是矢量數(shù)據(jù)庫(kù)有了深入的了解,讓我們深入了解為什么它們?cè)谌斯ぶ悄芎蜋C(jī)器學(xué)習(xí)領(lǐng)域如此必要。
這里的關(guān)鍵詞是性能。矢量數(shù)據(jù)庫(kù)通常每次查詢處理數(shù)億個(gè)向量,這種性能比傳統(tǒng)數(shù)據(jù)庫(kù)在處理向量時(shí)能夠達(dá)到的性能要快得多。
那么,是什么讓矢量數(shù)據(jù)庫(kù)如此快速高效呢?讓我們來(lái)看看使它們與眾不同的一些關(guān)鍵功能。
復(fù)雜的數(shù)學(xué)運(yùn)算向量數(shù)據(jù)庫(kù)旨在對(duì)向量執(zhí)行復(fù)雜的數(shù)學(xué)運(yùn)算,例如過濾和定位“附近”向量。這些操作在機(jī)器學(xué)習(xí)環(huán)境中至關(guān)重要,其中模型通常需要在高維空間中找到彼此接近的向量。
例如,一種常見的數(shù)據(jù)分析技術(shù)余弦相似性通常用于測(cè)量?jī)蓚€(gè)向量的相似程度。矢量數(shù)據(jù)庫(kù)擅長(zhǎng)這些類型的計(jì)算。
專用矢量索引與組織良好的庫(kù)一樣,數(shù)據(jù)庫(kù)需要一個(gè)良好的索引系統(tǒng)來(lái)快速檢索請(qǐng)求的數(shù)據(jù)。矢量數(shù)據(jù)庫(kù)提供專門的矢量索引,與傳統(tǒng)數(shù)據(jù)庫(kù)相比,檢索數(shù)據(jù)的速度更快、更確定(與隨機(jī)數(shù)據(jù)庫(kù)相反)。
借助這些索引,向量數(shù)據(jù)庫(kù)可以快速定位 AI 模型所需的向量并快速生成結(jié)果。
緊湊的存儲(chǔ)在大數(shù)據(jù)的世界里,存儲(chǔ)空間是一種寶貴的商品。矢量數(shù)據(jù)庫(kù)在這里也大放異彩,以使其更緊湊的方式存儲(chǔ)矢量。壓縮和量化向量等技術(shù)用于在內(nèi)存中保留盡可能多的數(shù)據(jù),從而進(jìn)一步減少負(fù)載和查詢延遲。
分片在處理大量數(shù)據(jù)時(shí),將數(shù)據(jù)分布在多臺(tái)機(jī)器上可能是有益的,這個(gè)過程稱為分片。許多數(shù)據(jù)庫(kù)都可以執(zhí)行此操作,但 SQL 數(shù)據(jù)庫(kù)尤其需要付出更多努力才能橫向擴(kuò)展。另一方面,矢量數(shù)據(jù)庫(kù)通常在其架構(gòu)中內(nèi)置分片,使它們能夠輕松處理大量數(shù)據(jù)。
簡(jiǎn)而言之,雖然傳統(tǒng)數(shù)據(jù)庫(kù)可以存儲(chǔ)和對(duì)向量執(zhí)行操作,但它們并未針對(duì)任務(wù)進(jìn)行優(yōu)化。另一方面,矢量數(shù)據(jù)庫(kù)正是為此目的而構(gòu)建的。它們提供了處理大量矢量數(shù)據(jù)所需的速度、效率和專用工具,使其成為人工智能和機(jī)器學(xué)習(xí)領(lǐng)域必不可少的工具。
在下一節(jié)中,我們將向量數(shù)據(jù)庫(kù)與其他類型的數(shù)據(jù)庫(kù)進(jìn)行比較,并解釋它們?nèi)绾芜m應(yīng)更大的數(shù)據(jù)庫(kù)生態(tài)系統(tǒng)。我們才剛剛開始!
實(shí)現(xiàn)矢量數(shù)據(jù)庫(kù):分步指南出于本指南的目的,我們將使用 Weaviate(一種流行的矢量數(shù)據(jù)庫(kù)服務(wù))來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的矢量數(shù)據(jù)庫(kù),您可以基于該數(shù)據(jù)庫(kù)為任何用例進(jìn)行構(gòu)建。
您可以在此處克隆初學(xué)者模板并運(yùn)行以進(jìn)行設(shè)置。npm install
先決條件先前的JS知識(shí)將有所幫助:本教程中編寫的所有代碼都將使用JavaScript,我們也將使用Weaviate JavaScript SDK。
Node 和 npm:我們將在服務(wù)器上的 JavaScript 環(huán)境中工作。
OpenAI API密鑰:我們將使用他們的嵌入模型將我們的數(shù)據(jù)轉(zhuǎn)換為嵌入以存儲(chǔ)在我們的數(shù)據(jù)庫(kù)中
Weaviate帳戶:我們將使用他們的托管數(shù)據(jù)庫(kù)服務(wù);您可以在此處獲得免費(fèi)帳戶
創(chuàng)建帳戶后,您需要通過Weaviate儀表板設(shè)置項(xiàng)目。轉(zhuǎn)到 WCS 控制臺(tái),然后單擊創(chuàng)建集群:
選擇“免費(fèi)沙盒”層并提供群集名稱。當(dāng)它要求您啟用身份驗(yàn)證時(shí),請(qǐng)選擇“是”:
單擊創(chuàng)建。幾分鐘后,您應(yīng)該會(huì)在完成后看到一個(gè)復(fù)選標(biāo)記。
單擊“詳細(xì)信息”以查看群集詳細(xì)信息,因?yàn)槲覀儗⒃谙乱徊糠钟玫剿鼈?。其中包括?/p>
一個(gè)編織的****
身份驗(yàn)證詳細(xì)信息(Weaviate API 密鑰;單擊密鑰圖標(biāo)以顯示)
有了先決條件,我們可以創(chuàng)建向量數(shù)據(jù)庫(kù)并查詢它。要繼續(xù)操作,您需要一個(gè)新的 Node 項(xiàng)目;您可以在此處克隆 GitHub 上的模板,其中包括入門所需的一切。
或者,您可以通過運(yùn)行以下命令創(chuàng)建一個(gè):
mkdir weaviate-vector-database && cd weaviate-vector-database
npm init -y && npm install dotenv openai weaviate-ts-client
mkdir src
編輯文件并添加腳本,如下所示:package.jsonstart
// ...rest of package.json
"scripts": {
"start": "node src/index.js"
},
// ...rest of package.json
創(chuàng)建一個(gè)文件來(lái)存儲(chǔ)敏感信息,如 API 密鑰。編寫命令并在代碼編輯器中打開新創(chuàng)建的文件,然后粘貼以下內(nèi)容并確保將占位符替換為實(shí)際值:.envtouch .env.env
// .env
OPENAI_KEY="<OPENAI_API_KEY>"
WEAVIATE_API_KEY="<WEAVIATE_API_KEY>"
WEAVIATE_URL="<WEAVIATE_URL>"
DATA_CLASSNAME="Document"
項(xiàng)目設(shè)置完成后,我們可以添加一些代碼來(lái)設(shè)置和使用我們的矢量數(shù)據(jù)庫(kù)。讓我們快速總結(jié)一下我們將要實(shí)現(xiàn)的內(nèi)容:
幫助程序函數(shù),它:
連接到我們的數(shù)據(jù)庫(kù)
批量矢量化和上傳文檔
查詢最相似的項(xiàng)目
一個(gè) main 函數(shù),它使用上面的輔助函數(shù)一次性上傳文檔和查詢數(shù)據(jù)庫(kù)
話雖如此,讓我們創(chuàng)建第一個(gè)文件來(lái)存儲(chǔ)數(shù)據(jù)庫(kù)連接和幫助程序函數(shù)。通過運(yùn)行創(chuàng)建一個(gè)新文件,讓我們開始填寫它:touch src/database.js
// src/database.js
import weaviate, { ApiKey } from "weaviate-ts-client";
import { config } from "dotenv";
config();
async function setupClient() {
let client;
try {
client = weaviate.client({
scheme: "https",
host: process.env.WEAVIATE_URL,
apiKey: new ApiKey(process.env.WEAVIATE_API_KEY),
headers: { "X-OpenAI-Api-Key": process.env.OPENAI_API_KEY },
});
} catch (err) {
console.error("error >>>", err.message);
}
return client;
}
// ... code continues below
讓我們分解一下這里發(fā)生的事情。首先,我們導(dǎo)入必要的軟件包,Weaviate客戶端和dotenv配置。dotenv 是一個(gè)將環(huán)境變量從文件加載到 .Weaviate和OpenAI密鑰和URL通常存儲(chǔ)在環(huán)境變量中,以保持機(jī)密性并遠(yuǎn)離代碼庫(kù)。.envprocess.env
以下是函數(shù)中發(fā)生的情況:setupClient()
我們初始化了一個(gè)變量client
我們有一個(gè)塊,用于設(shè)置與 Weaviate 服務(wù)器的連接。如果在此過程中發(fā)生任何錯(cuò)誤,我們會(huì)將錯(cuò)誤消息打印到控制臺(tái)try…catch
在塊內(nèi),我們使用該方法創(chuàng)建一個(gè)新的 Weaviate 客戶端。、 和 參數(shù)取自我們?cè)O(shè)置的環(huán)境變量tryweaviate.client()schemehostapiKey
最后,我們傳入OpenAI的標(biāo)頭,因?yàn)槲覀儗⑹褂肙penAI的Ada模型來(lái)矢量化我們的數(shù)據(jù)。
設(shè)置客戶端后,讓我們使用一些虛擬數(shù)據(jù)、虛構(gòu)生物、地點(diǎn)和事件的集合來(lái)運(yùn)行遷移。稍后,我們將針對(duì)此數(shù)據(jù)查詢 GPT-3。
如果您沒有克隆初學(xué)者模板,請(qǐng)按照以下步驟操作:
通過運(yùn)行創(chuàng)建新文件touch src/data.js
從此處復(fù)制文件的內(nèi)容并將其粘貼到
花一些時(shí)間瀏覽 中的數(shù)據(jù)。然后,在文件頂部添加新導(dǎo)入:src/data.jssrc/database.js
// ...other imports
import { FAKE_XORDIA_HISTORY } from "./data";
在函數(shù)下方,添加一個(gè)新函數(shù),如下所示:setupClient
async function migrate(shouldDeleteAllDocuments = false) {
try {
const classObj = {
class: process.env.DATA_CLASSNAME,
vectorizer: "text2vec-openai",
moduleConfig: {
"text2vec-openai": {
model: "ada",
modelVersion: "002",
type: "text",
},
},
};
const client = await setupClient(); try { const schema = await client.schema .classCreator() .withClass(classObj) .do(); console.info("created schema >>>", schema); } catch (err) { console.error("schema already exists"); } if (!FAKE_XORDIA_HISTORY.length) { console.error(`Data is empty`); process.exit(1); } if (shouldDeleteAllDocuments) { console.info(`Deleting all documents`); await deleteAllDocuments(); } console.info(`Inserting documents`); await addDocuments(FAKE_XORDIA_HISTORY);
} catch (err) {
console.error("error >>>", err.message);
}
}
再一次,讓我們分解一下這里發(fā)生的事情。
該函數(shù)接受單個(gè)參數(shù),該參數(shù)確定在遷移數(shù)據(jù)時(shí)是否清除數(shù)據(jù)庫(kù)。migrateshouldDeleteAllDocuments
在我們的塊中,我們創(chuàng)建一個(gè)名為 .此對(duì)象表示 Weaviate 中類的架構(gòu)(確保在文件中添加 a),該類使用矢量化器。這決定了文本文檔在數(shù)據(jù)庫(kù)中的配置和表示方式,并告訴Weaviate使用OpenAI的“ada”模型對(duì)我們的數(shù)據(jù)進(jìn)行矢量化。try…catchclassObjCLASS_NAME.envtext2vec-openai
然后,我們使用方法鏈創(chuàng)建模式。這會(huì)向 Weaviate 服務(wù)器發(fā)送請(qǐng)求,以創(chuàng)建 中定義的文檔類。成功創(chuàng)建架構(gòu)后,我們將模式對(duì)象記錄到控制臺(tái),并顯示消息 .現(xiàn)在,錯(cuò)誤通過記錄到控制臺(tái)的簡(jiǎn)單消息進(jìn)行處理。client.schema.classCreator().withClass(classObj).do()classObjcreated schema >>>
我們可以檢查要遷移的虛擬數(shù)據(jù)的長(zhǎng)度。如果為空,則代碼在此處結(jié)束。我們可以使用函數(shù)(稍后會(huì)添加)清除數(shù)據(jù)庫(kù),如果 是 .deleteAllDocumentsshouldDeleteAllDocumentstrue
最后,使用一個(gè)函數(shù)(我們接下來(lái)將添加),我們上傳所有要矢量化并存儲(chǔ)在 Weaviate 中的條目。addDocuments
添加文檔我們可以繼續(xù)矢量化和上傳我們的文本文檔。這實(shí)際上是一個(gè)兩步過程,其中:
原始文本字符串使用 OpenAI Ada 模型轉(zhuǎn)換為矢量
轉(zhuǎn)換后的載體將上傳到我們的 Weaviate 數(shù)據(jù)庫(kù)
值得慶幸的是,這些是由我們使用的Weaviate SDK自動(dòng)處理的。讓我們繼續(xù)創(chuàng)建函數(shù)來(lái)執(zhí)行此操作。打開同一文件并粘貼以下內(nèi)容:src/database.js
// code continues from above
const addDocuments = async (data = []) => {
const client = await setupClient();
let batcher = client.batch.objectsBatcher();
let counter = 0;
const batchSize = 100;
for (const document of data) {
const obj = {
class: process.env.DATA_CLASSNAME,
properties: { ...document },
};
batcher = batcher.withObject(obj); if (counter++ == batchSize) { await batcher.do(); counter = 0; batcher = client.batch.objectsBatcher(); }
}
const res = await batcher.do();
return res;
};
// ... code continues below
和以前一樣,讓我們分解一下這里發(fā)生的事情。
首先,我們調(diào)用前面定義的函數(shù)來(lái)設(shè)置并獲取 Weaviate 客戶端實(shí)例setupClient()
我們使用初始化一個(gè)批處理器,用于收集文檔并一次性將它們上傳到Weaviate,使過程更高效client.batch.objectsBatcher()
我們還定義了一個(gè)計(jì)數(shù)器變量和一個(gè)變量,并將其設(shè)置為 100。計(jì)數(shù)器跟蹤已添加到當(dāng)前批次的文檔數(shù),并定義每個(gè)批次中應(yīng)包含的文檔數(shù)batchSizebatchSize
然后,我們遍歷數(shù)據(jù)數(shù)組中的每個(gè)文檔:
對(duì)于每個(gè)文檔,我們創(chuàng)建一個(gè)對(duì)象,該對(duì)象以Weaviate期望的格式表示文檔,以便可以將其擴(kuò)展到該對(duì)象的屬性中
然后,我們使用batcher.withObject(obj)
如果計(jì)數(shù)器等于批大?。ㄒ馕吨褲M),我們將批上傳到 Weaviate,將計(jì)數(shù)器重置為 ,并為下一批文檔創(chuàng)建一個(gè)新的批處理器batcher.do()0
處理完所有文檔并將其添加到批處理后,如果還有剩余的批處理尚未上載(因?yàn)樗吹竭_(dá) ),則可以使用 上載剩余的批處理。batchSizebatcher.do()
此處的最后一步發(fā)生在函數(shù)返回上次調(diào)用的響應(yīng)時(shí)。此響應(yīng)將包含有關(guān)上傳的詳細(xì)信息,例如上傳是否成功以及發(fā)生的任何錯(cuò)誤。batcher.do()
從本質(zhì)上講,該函數(shù)通過將大量文檔分組為可管理的批次來(lái)幫助我們有效地將大量文檔上傳到我們的 Weaviate 實(shí)例。addDocuments()
刪除文檔讓我們添加函數(shù)中使用的代碼。在函數(shù)下方,添加以下代碼:deleteAllDocumentsmigrateaddDocuments
// code continues from above
async function deleteAllDocuments() {
const client = await setupClient();
const documents = await client.graphql
.get()
.withClassName(process.env.DATA_CLASSNAME)
.withFields("_additional { id }")
.do();
for (const document of documents.data.Get[process.env.DATA_CLASSNAME]) {
await client.data
.deleter()
.withClassName(process.env.DATA_CLASSNAME)
.withId(document._additional.id)
.do();
}
}
// ... code continues below
這個(gè)函數(shù)相對(duì)簡(jiǎn)單。
我們使用類名為setupClientidDocument
然后使用循環(huán),我們使用其刪除每個(gè)文檔for...ofid
這種方法之所以有效,是因?yàn)槲覀儞碛猩倭繑?shù)據(jù)。對(duì)于較大的數(shù)據(jù)庫(kù),需要一種技術(shù)來(lái)刪除所有文檔,因?yàn)槊總€(gè)請(qǐng)求的限制是一次只有 200 個(gè)條目。batching
向數(shù)據(jù)庫(kù)添加查詢函數(shù)現(xiàn)在我們有了將數(shù)據(jù)上傳到數(shù)據(jù)庫(kù)的方法,讓我們添加一個(gè)函數(shù)來(lái)查詢數(shù)據(jù)庫(kù)。在本例中,我們將執(zhí)行“最近鄰搜索”以查找與我們的查詢相似的文檔。
在同一文件中,添加以下內(nèi)容:src/database.js
// code continues from above
async function nearTextQuery({
concepts = [""],
fields = "text category",
limit = 1,
}) {
const client = await setupClient();
const res = await client.graphql
.get()
.withClassName("Document")
.withFields(fields)
.withNearText({ concepts })
.withLimit(limit)
.do();
return res.data.Get[process.env.DATA_CLASSNAME];
}
export { migrate, addDocuments, deleteAllDocuments, nearTextQuery };
同樣,讓我們對(duì)這里發(fā)生的事情進(jìn)行細(xì)分:
nearTextQuery()是一個(gè)接受對(duì)象作為參數(shù)的異步函數(shù)。此對(duì)象可以包含三個(gè)屬性:
概念:表示我們正在搜索的術(shù)語(yǔ)的字符串?dāng)?shù)組
字段:一個(gè)字符串,表示我們希望在搜索結(jié)果中返回的字段。在本例中,我們從 和 字段請(qǐng)求textcategory
限制:我們希望從搜索查詢中返回的最大結(jié)果數(shù)
我們調(diào)用函數(shù)來(lái)獲取 Weaviate 客戶端實(shí)例setupClient()
我們使用一系列方法構(gòu)建 GraphQL 查詢:
client.graphql.get():初始化 GraphQL 查詢
.withClassName("Document"):我們指定要在“文檔”對(duì)象中搜索
.withFields(fields):我們指定要在結(jié)果中返回哪些字段
.withNearText({ concepts }):這就是魔術(shù)發(fā)生的地方!我們指定了 Weaviate 將用于搜索語(yǔ)義相似的文檔的概念
.withLimit(limit):我們指定要返回的最大結(jié)果數(shù)
最后,執(zhí)行查詢.do()
來(lái)自查詢的響應(yīng)存儲(chǔ)在變量中,然后在下一行返回res
最后,我們導(dǎo)出此處定義的所有函數(shù)以在其他地方使用
簡(jiǎn)而言之,該函數(shù)幫助我們根據(jù)提供的術(shù)語(yǔ)在 Weaviate 實(shí)例中搜索語(yǔ)義相似的文檔。nearTextQuery()
讓我們遷移數(shù)據(jù),以便在下一節(jié)中查詢它。打開終端并運(yùn)行 。npm run start"migrate"
結(jié)合向量嵌入和 AI像 GPT-3 和 ChatGPT 這樣的大型語(yǔ)言模型旨在處理輸入并生成有用的輸出,這是一項(xiàng)需要了解單詞和短語(yǔ)之間復(fù)雜含義和關(guān)系的任務(wù)。
他們通過將單詞、句子甚至整個(gè)文檔表示為高維向量來(lái)做到這一點(diǎn)。通過分析這些向量之間的異同,人工智能模型可以理解我們語(yǔ)言中的上下文、語(yǔ)義甚至細(xì)微差別。
那么,矢量數(shù)據(jù)庫(kù)從何而來(lái)?讓我們將矢量數(shù)據(jù)庫(kù)視為 AI 模型的圖書館員。在龐大的書籍庫(kù)(或者,在我們的例子中,向量)中,人工智能模型需要快速找到與特定查詢最相關(guān)的書籍。矢量數(shù)據(jù)庫(kù)通過有效地存儲(chǔ)這些“書籍”并在需要時(shí)提供快速精確的檢索來(lái)實(shí)現(xiàn)這一點(diǎn)。
這對(duì)于許多AI應(yīng)用程序至關(guān)重要。例如,在聊天機(jī)器人應(yīng)用程序中,AI 模型需要找到對(duì)用戶問題最相關(guān)的響應(yīng)。它通過將用戶的問題和潛在響應(yīng)轉(zhuǎn)換為向量,然后使用向量數(shù)據(jù)庫(kù)查找與用戶問題最相似的響應(yīng)來(lái)實(shí)現(xiàn)這一點(diǎn)。
考慮到這一點(diǎn),我們將使用上面的數(shù)據(jù)庫(kù)來(lái)提供一個(gè) AI 模型 GPT-3.5,其中包含我們自己數(shù)據(jù)的上下文。這將允許模型回答有關(guān)未訓(xùn)練的數(shù)據(jù)的問題。
人工智能模型設(shè)置通過運(yùn)行并粘貼以下內(nèi)容來(lái)創(chuàng)建新文件:touch src/data.js
import { Configuration, OpenAIApi } from "openai";
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
async function getChatCompletion({ prompt, context }) {
const chatCompletion = await openai.createChatCompletion({
model: "gpt-3.5-turbo",
messages: [
{
role: "system",
content: You are a knowledgebase oracle. You are given a question and a context. You answer the question based on the context. Analyse the information from the context and draw fundamental insights to accurately answer the question to the best of your ability. Context: ${context} ,
},
{ role: "user", content: prompt },
],
});
return chatCompletion.data.choices[0].message;
}
export { getChatCompletion };
像往常一樣,讓我們分解一下文件:
我們從包中導(dǎo)入一些必需的模塊并初始化一個(gè)實(shí)例openaiopenai
我們定義了一個(gè)函數(shù),該函數(shù)接受提示、一些上下文,并將 GPT-3.5 模型配置為作為知識(shí)庫(kù)預(yù)言機(jī)進(jìn)行響應(yīng)getChatCompletion
最后,我們返回響應(yīng)并導(dǎo)出函數(shù)
通過設(shè)置我們的矢量數(shù)據(jù)庫(kù)和 AI 模型,我們最終可以通過結(jié)合這兩個(gè)系統(tǒng)來(lái)查詢我們的數(shù)據(jù)。利用嵌入的強(qiáng)大效果和 GPT-3.5 令人印象深刻的自然語(yǔ)言功能,我們將能夠以更具表現(xiàn)力和可定制的方式與我們的數(shù)據(jù)進(jìn)行交互。
首先創(chuàng)建一個(gè)新文件并運(yùn)行 .然后粘貼以下內(nèi)容:touch src/index.js
import { config } from "dotenv";
import { nearTextQuery } from "./database.js";
import { getChatCompletion } from "./model.js";
config();
const queryDatabase = async (prompt) => {
console.info(Querying database);
const questionContext = await nearTextQuery({
concepts: [prompt],
fields: "title text date",
limit: 50,
});
const context = questionContext
.map((context, index) => {
const { title, text, date } = context;
return Document ${index + 1} Date: ${date} Title: ${title} ${text} ;
})
.join("\n\n");
const aiResponse = await getChatCompletion({ prompt, context });
return aiResponse.content;
};
const main = async () => {
const command = process.argv[2];
const params = process.argv[3];
switch (command) {
case "migrate":
return await migrate(params === "--delete-all");
case "query":
return console.log(await queryDatabase(params));
default:
// do nothing
break;
}
};
main();
在此文件中,我們將到目前為止所做的所有工作匯集在一起,以允許我們通過命令行查詢數(shù)據(jù)。像往常一樣,讓我們探討一下這里發(fā)生了什么:
首先,我們導(dǎo)入必要的模塊并使用包設(shè)置我們的環(huán)境變量dotenv
接下來(lái),我們創(chuàng)建一個(gè)接受文本提示的函數(shù),我們使用它對(duì)向量數(shù)據(jù)庫(kù)執(zhí)行“近文本”查詢。我們將結(jié)果限制為 50 個(gè),并且我們特別要求提供匹配概念的“標(biāo)題”、“文本”和“日期”字段queryDatabase
這基本上返回了語(yǔ)義上類似于我們搜索查詢中的任何重要術(shù)語(yǔ)的文檔(嵌入功能強(qiáng)大!
然后,我們映射接收到的上下文,對(duì)其進(jìn)行格式化,并將其傳遞給AI模型以生成完成。使用上下文,GPT-3.5 的自然語(yǔ)言處理 (NLP) 功能大放異彩,因?yàn)樗軌蚋鶕?jù)我們的數(shù)據(jù)生成更準(zhǔn)確和有意義的響應(yīng)
最后,我們到達(dá)函數(shù)。在這里,我們使用命令行參數(shù)來(lái)執(zhí)行各種任務(wù)。如果我們通過,我們可以遷移我們的數(shù)據(jù)(帶有可選標(biāo)志,以防萬(wàn)一我們想清理我們的石板并重新開始),并且有了,我們可以測(cè)試我們的查詢函數(shù)mainmigrate--delete-allquery
祝賀。如果你走到了這一步,你應(yīng)該得到拍拍——你終于可以測(cè)試你的代碼了。
打開終端并運(yùn)行以下命令:
npm run start "query" "what are the 3 most impressive achievements of humanity in the story?"
查詢將發(fā)送到您的 Weaviate 矢量數(shù)據(jù)庫(kù),在那里它與其他類似矢量進(jìn)行比較,并根據(jù)其文本返回 50 個(gè)最相似的矢量。然后,此上下文數(shù)據(jù)將被格式化并與您的查詢一起發(fā)送到 OpenAI 的 GPT-3.5 模型,在那里對(duì)其進(jìn)行處理并生成響應(yīng)。
如果一切順利,您應(yīng)該得到與以下類似的響應(yīng):
隨意探索這個(gè)虛構(gòu)的世界,更多的查詢,或者更好的是,帶上自己的數(shù)據(jù),親眼目睹向量和嵌入的力量。
如果此時(shí)遇到任何錯(cuò)誤,請(qǐng)?jiān)诖颂帉⒛拇a與最終版本進(jìn)行比較,并確保已創(chuàng)建并填寫文件。.env
結(jié)論和今后的步驟在本教程中,我們略微探索了矢量和矢量數(shù)據(jù)庫(kù)的強(qiáng)大功能。使用Weaviate和GPT-3等工具,我們親眼目睹了這些技術(shù)在塑造AI應(yīng)用程序方面的潛力,從改進(jìn)個(gè)性化聊天機(jī)器人到增強(qiáng)機(jī)器學(xué)習(xí)算法。請(qǐng)務(wù)必也看看我們的GitHub!
然而,這僅僅是個(gè)開始。如果您想了解有關(guān)使用矢量數(shù)據(jù)庫(kù)的更多信息,請(qǐng)考慮:
深入了解高級(jí)概念,例如使用矢量元數(shù)據(jù)、分片、壓縮,以實(shí)現(xiàn)更靈活、更高效的數(shù)據(jù)存儲(chǔ)和檢索
嘗試更復(fù)雜的方法將向量嵌入集成到 AI 應(yīng)用程序中,以獲得更豐富、更細(xì)微的結(jié)果
感謝您堅(jiān)持到最后,希望這是對(duì)您的時(shí)間的有效利用。
您是否正在添加新的 JS 庫(kù)以提高性能或構(gòu)建新功能?如果他們反其道而行之呢?毫無(wú)疑問,前端變得越來(lái)越復(fù)雜。當(dāng)您向應(yīng)用添加新的 JavaScript 庫(kù)和其他依賴項(xiàng)時(shí),您將需要更高的可見性,以確保您的用戶不會(huì)遇到未知問題。
LogRocket 是一個(gè)前端應(yīng)用程序監(jiān)控解決方案,可讓您重播 JavaScript 錯(cuò)誤,就好像它們發(fā)生在您自己的瀏覽器中一樣,這樣您就可以更有效地對(duì)錯(cuò)誤做出反應(yīng)。
LogRocket 可以完美地與任何應(yīng)用程序配合使用,無(wú)論框架如何,并且具有用于記錄來(lái)自 Redux、Vuex 和 @ngrx/store 的其他上下文的插件。無(wú)需猜測(cè)問題發(fā)生的原因,您可以匯總并報(bào)告問題發(fā)生時(shí)應(yīng)用程序所處的狀態(tài)。LogRocket 還會(huì)監(jiān)控應(yīng)用的性能,報(bào)告客戶端 CPU 負(fù)載、客戶端內(nèi)存使用情況等指標(biāo)。
原文鏈接:如何實(shí)現(xiàn)AI的矢量數(shù)據(jù)庫(kù) (mvrlink.com)
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。