iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
自我挑戰組

AI 不只會回答:30 天打造一套真正能上線的智慧助理系列 第 5

[Day 5] 建立第一個 Vector Database:讓 AI 助理搜尋自己的知識庫

  • 分享至 

  • xImage
  •  

[Day 5] 建立第一個 Vector Database:讓 AI 助理搜尋自己的知識庫

Day 4 我們理解了 Embedding

我們知道文字可以透過 Embedding Model 轉換成向量

也知道使用者的問題同樣可以轉換成 Vector,接著透過相似度搜尋,找到與問題最相關的文件內容

但目前這還不能稱為一個真正的 RAG 系統

因為我們還缺少一個非常重要的要素

Vector Database (向量資料庫)

今天就來實際建立 Vector Database,讓我們的 AI 助理第一次真正具備:

「搜尋自己的知識庫」


為什麼需要 Vector Database

假設我們今天有一份文件:

本產品支援 Windows 10、Windows 11 以及 Ubuntu 22.04 與 Ubuntu 24.04

使用者可以透過官方網站下載安裝程式

安裝完成後,需要重新啟動系統

經過 Day 3 的 Chunking

Chunk 1
本產品支援 Windows 10、Windows 11 以及 Ubuntu 22.04 與 Ubuntu 24.04。

Chunk 2
使用者可以透過官方網站下載安裝程式。

Chunk 3
安裝完成後,需要重新啟動系統。

再經過 Day 4 的 Embedding

Chunk 1 → Vector 1
Chunk 2 → Vector 2
Chunk 3 → Vector 3

問題來了:

這些 Vector 要放在哪裡

如果只是存在變數裡,程式一關閉,資料就消失了

而且當文件一堆資訊

我們也不可能每次都重新把所有資料處理一次

因此,我們需要一個專門儲存與搜尋向量的系統

這就是:

Vector Database

Vector Database 到底存什麼

一個 Vector Database 中,通常不會只有 Vector

實際上我們會一起儲存向量 + 原始文字

這樣當搜尋找到某個 Vector 時,我們才能知道:

「這個 Vector 原本是哪一段文字」

Vector Database 與一般 Database 有什麼不同

這是一個很容易混淆的地方

一般資料庫比較擅長具有明確條件的資料查詢

但是 RAG 的問題通常不是這麼明確

使用者可能問:

「這個產品可以在哪些作業系統上使用」

我們不一定知道答案中會出現什麼

甚至使用者可能問:

「這套系統能不能裝在微軟最新的桌面作業系統」

這時候單純做關鍵字比對可能不夠

Vector Database 可以透過向量相似度進行:

Semantic Search (語意搜尋)

Keyword Search vs. Semantic Search

假設文件中有:

本產品支援 Windows 11

使用者問:

「這個軟體可以裝在哪個作業系統」

Keyword Search

搜尋:

軟體
作業系統

文件裡不一定有完全相同的詞

因此可能找不到

Semantic Search

使用 Embedding 即使文字不完全相同,只要語意足夠接近,就有機會被搜尋出來

這就是 Vector Database 在 RAG 裡的重要性

今天使用 Chroma

今天我們使用:

Chroma

作為本地端的 Vector Database

原因很簡單:

  • Python 使用方便
  • 適合 RAG Prototype
  • 可以直接在本機執行
  • 不需要先架設額外資料庫服務
  • 很適合拿來理解 Vector Database 的運作方式

今天的目標不是探討所有 Vector Database

而是先真正完成整體架構

安裝套件

首先安裝:

pip install chromadb sentence-transformers

如果 Day 3 已經安裝:

langchain-text-splitters

則可以繼續使用

Step 1:建立 Chroma Client

建立:

import chromadb


client = chromadb.PersistentClient(
    path="./data/chroma"
)

這裡使用:

PersistentClient

代表資料會儲存在本機

程式關閉之後,Vector Database 的資料仍然存在

Step 2:建立 Collection

接著建立一個 Collection:

collection = client.get_or_create_collection(
    name="knowledge_base"
)

可以把 Collection 想成一個資料集合

未來如果有不同知識領域,也可以建立不同 Collection

Step 3:準備文件

延續 Day 3 的:

內容:

本產品支援 Windows 10、Windows 11 以及 Ubuntu 22.04 與 Ubuntu 24.04

使用者可以透過官方網站下載安裝程式

安裝完成後,需要重新啟動系統

先讀取:

with open(
    "data/sample.txt",
    "r",
    encoding="utf-8"
) as f:
    text = f.read()

Step 4:進行 Chunking

使用 Day 3 的方式:

from langchain_text_splitters import RecursiveCharacterTextSplitter


splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=20
)

chunks = splitter.split_text(text)

實際 Chunk 數量會依文字內容與切割設定而有所不同


Step 5:建立 Embedding Model

接著使用 Day 4 的 Embedding:

from sentence_transformers import SentenceTransformer


model = SentenceTransformer(
    "all-MiniLM-L6-v2"
)

將 Chunk 轉換成 Vector:

embeddings = model.encode(chunks)

現在:

Chunk 1 → Vector 1
Chunk 2 → Vector 2
Chunk 3 → Vector 3

Step 6:將資料存進 Chroma

接著把資料加入 Vector Database:

collection.add(
    ids=[f"chunk-{i}" for i in range(len(chunks))],
    documents=chunks,
    embeddings=embeddings.tolist(),
    metadatas=[
        {
            "source": "sample.txt"
        }
        for _ in chunks
    ]
)

這時候資料就真正進入 Chroma

完整建立 Vector Database

把前面的內容整合起來:

import chromadb

from langchain_text_splitters import RecursiveCharacterTextSplitter
from sentence_transformers import SentenceTransformer


# 讀取文件
with open(
    "data/sample.txt",
    "r",
    encoding="utf-8"
) as f:
    text = f.read()


# Chunking
splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=20
)

chunks = splitter.split_text(text)


# Embedding Model
model = SentenceTransformer(
    "all-MiniLM-L6-v2"
)

embeddings = model.encode(chunks)


# 建立 Chroma
client = chromadb.PersistentClient(
    path="./data/chroma"
)

collection = client.get_or_create_collection(
    name="knowledge_base"
)


# 儲存資料
collection.add(
    ids=[
        f"chunk-{i}"
        for i in range(len(chunks))
    ],
    documents=chunks,
    embeddings=embeddings.tolist(),
    metadatas=[
        {
            "source": "sample.txt"
        }
        for _ in chunks
    ]
)


print(f"成功建立 {len(chunks)} 個 Chunks")

如果成功,可以看到:

成功建立 3 個 Chunks

實際數量會依 Chunking 設定而不同

現在開始搜尋知識庫

前面完成的是建立 Knowledge Base

現在開始做 RAG 的另一半:

假設使用者問:

query = "這個產品支援哪些作業系統"

先轉成 Embedding
接著搜尋 Chroma

results = collection.query(
    query_embeddings=query_embedding.tolist(),
    n_results=2
)

代表希望取得最相關的 2 個結果


查看搜尋結果

加入:

print(results["documents"])

可能得到:

[
    [
        "本產品支援 Windows 10、Windows 11...",
        "以及 Ubuntu 22.04 與 Ubuntu 24.04..."
    ]
]

這就是我們第一次真正完成:

「搜尋自己的知識庫」

到這裡,我們已經完成真正的 Retrieval

這裡最重要的是:

我們還沒有讓 LLM 回答

目前系統只能做到:

「幫我找相關資料」

但這其實已經是 RAG 非常重要的一半

Retrieval 與 Generation

RAG 的名字其實已經告訴我們它包含兩件事情 Retrieval + Generation

Retrieval

負責:

找資料

Generation

負責:

根據資料產生答案

為什麼今天還沒有加入 LLM

因為我們希望把 RAG 拆開

如果今天直接使用

可能只需要幾行程式就可以完成

但我們可能不知道:

Chunk 是怎麼來的

Vector 是怎麼產生的

Search 是怎麼找到資料的

為什麼這個 Chunk 被找到

因此這 30 天的目標不是:

「用最少的程式碼做出 RAG」

而是:

「真正理解一個 AI Application 是怎麼組成的」

Top-K 是什麼

這個概念通常可以理解為:

Top-K Retrieval

也就是:

找出最相關的 K 個 Chunk

都會提供給後面的 LLM

Top-K 不是越大越好

假設:

K = 1

可能發生:

只找到一小段資訊 + Context 不完整

但如果:

K = 20

又可能變成大量無關內容 + Context 增加 + Token 增加 + LLM 負擔增加

因此:

Top-K 需要根據實際資料進行實驗

後面可以進一步測試,觀察不同 K 值對 Retrieval 與回答品質的影響

Metadata 有什麼用途

前面我們存入:

metadatas=[
    {
        "source": "sample.txt"
    }
]

這就是 Metadata

實際 RAG 系統可能包含:

{
    "source": "product_manual.pdf",
    "page": 12,
    "section": "System Requirements",
    "document_type": "manual"
}

這些資訊可以幫助我們:

知道資料來源

答案來自哪一份文件

知道頁碼

PDF 第幾頁

進行 Filter

例如:

只搜尋產品手冊

而不是:

所有文件

因此一個成熟的 RAG 系統,不應該只關心 Chunk + Vector

也需要好好設計 Metadata

今天的 RAG 已經走到哪裡

如果把前幾天串起來:

Day 3

Chunking

Day 4

Vector Embedding

Day 5

Similarity Search

我們已經完成 RAG 的資料檢索基礎

今天的小實驗

今天可以實際測試不同問題

問題 1

這個產品支援哪些作業系統

預期找到:

Windows
Ubuntu

問題 2

安裝完成後需要做什麼

預期找到:

安裝完成後,需要重新啟動系統

問題 3

要去哪裡下載安裝程式

預期找到:

使用者可以透過官方網站下載安裝程式

問題 4

這個產品支援 macOS 嗎

這是一個很重要的測試。

因為文件中並沒有:

macOS

我們要觀察:

Vector Search 會找到什麼

以及:

如果沒有足夠證據,後面的 AI 能不能正確回答「文件沒有提供相關資訊」

這會在後面的 RAG Evaluation 控制中繼續處理

今天的重點

今天我們第一次建立了一個真正可以工作的 Vector Database

我們也理解了幾個重要概念:

  • Vector Database 是什麼
  • Vector Database 與一般 Database 的差異
  • Semantic Search
  • Top-K
  • Metadata
  • Retrieval
  • Retrieval 與 Generation 的差異

而目前的 AI 助理已經開始具備一個很重要的能力:

它不只會回答問題,而是開始懂得「去哪裡找資料」

下一步:讓 LLM 真正使用搜尋結果

我們還沒有讓 LLM 根據這些資料回答

這時候,我們才會真正完成:

第一個可以根據自己的知識庫回答問題的 RAG Chatbot

[Day 6] 我們就把 Vector Search 與 LLM 串起來,讓 AI 助理真正「看著資料回答問題」


上一篇
[Day 4] Embedding:文字到底是怎麼變成機器能比較的向量形式
下一篇
[Day 6] 串接 Vector Search 與 LLM 讓 AI 助理真正看著資料回答問題
系列文
AI 不只會回答:30 天打造一套真正能上線的智慧助理6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言