iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0
AI Engineering

從零打造 RAG 系統:檢索、生成與落地全紀錄系列 第 12 篇

[Day 12] 建立索引:從文字到向量的完整流程

  • 分享至 

  • xImage
  •  

前言

前幾天分別談了 Embedding 與向量資料庫的選型,今天要把兩者串接起來,實際把 Day 9 產出的 chunk 資料,轉換成向量並寫入資料庫,完成 Indexing 階段的最後一哩路。

完整流程回顧

原始文件 → 前處理 Pipeline(Day 5-9) → chunk 清單
                                            │
                                            ▼
                                  逐筆呼叫 Embedding API
                                            │
                                            ▼
                              寫入向量資料庫(含 content + embedding + metadata)
                                            │
                                            ▼
                                      建立索引,等待查詢

實作:批次寫入向量資料庫

import psycopg2
from psycopg2.extras import execute_values

def insert_chunks_to_db(chunks, conn):
    """
    chunks: [{"content": ..., "embedding": [...], "metadata": {...}}, ...]
    """
    cur = conn.cursor()
    data = [
        (c["content"], c["embedding"], psycopg2.extras.Json(c["metadata"]))
        for c in chunks
    ]
    execute_values(
        cur,
        "INSERT INTO chunks (content, embedding, metadata) VALUES%s",
        data,
        template="(%s,%s,%s)"
    )
    conn.commit()
    cur.close()

批次寫入(execute_values)相較於逐筆 INSERT,可以大幅減少資料庫往返次數,加快寫入速度。

整合前處理 + Embedding + 寫入的完整腳本

def build_index(doc_dir, conn):
    all_chunks = []
    for file_path in doc_dir.glob("**/*"):
        if file_path.suffix in [".pdf", ".html", ".md"]:
            chunks = preprocess_pipeline(file_path)  # Day 9 的 Pipeline
            all_chunks.extend(chunks)

    # 批次做 Embedding(可依 API 限制調整批次大小)
    batch_size = 50
    for i in range(0, len(all_chunks), batch_size):
        batch = all_chunks[i:i+batch_size]
        texts = [c["content"] for c in batch]
        embeddings = get_embeddings_batch(texts)  # 批次呼叫 Embedding API
        for c, emb in zip(batch, embeddings):
            c["embedding"] = emb

    insert_chunks_to_db(all_chunks, conn)
    print(f"共處理{len(all_chunks)} 個 chunk,已寫入資料庫")

處理大量文件時的注意事項

  • API Rate Limit:Embedding API 通常有每分鐘請求數限制,大量文件建議加入延遲或使用官方的批次端點
  • 記憶體用量:文件量大時,不要一次把所有 chunk 都讀進記憶體,可以分批處理
  • 重複資料:文件如果更新過,避免重複寫入相同內容,建議先用 Day 9 提到的增量更新機制判斷是否需要重新處理

驗證索引是否建立成功

-- 檢查資料筆數
SELECT COUNT(*) FROM chunks;

-- 檢查是否有 embedding 為 NULL 的異常資料
SELECT COUNT(*) FROM chunks WHERE embedding IS NULL;

-- 簡單測試相似度搜尋是否能運作
SELECT content FROM chunks
ORDER BY embedding <=> (SELECT embedding FROM chunks LIMIT 1)
LIMIT 5;

小結

到這裡,Indexing 階段的完整流程——文件前處理、Chunking、Embedding、寫入向量資料庫——已經串接完成。這代表我們的知識庫已經「可以被查詢」了。明天開始,我們要進入 Retrieval 階段,先從最基礎的相似度搜尋原理談起。


上一篇
[Day 11] 向量資料庫選型:從 Chroma 到 pgvector 到 Milvus
系列文
從零打造 RAG 系統:檢索、生成與落地全紀錄 共 12 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言