建立索引
索引階段發生在使用者提問之前。目標是:之後任何問題,都能在幾百毫秒內拿到「可能有用的幾段原文」。
四個步驟
- 載入:PDF、Markdown、網頁、資料庫列。先抽出純文字;掃描件要 OCR。垃圾進、垃圾出。
- 切塊:見 切塊。同時寫入來源、標題、頁碼。
- 嵌入:見 嵌入。批次呼叫,注意 rate limit。
- 寫入向量庫:向量 + 原文 + metadata。給每個塊穩定的 id,方便之後更新。
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
docs = PyPDFLoader("handbook.pdf").load()
chunks = RecursiveCharacterTextSplitter(
chunk_size=800, chunk_overlap=120
).split_documents(docs)
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=OpenAIEmbeddings(model="text-embedding-3-small"),
persist_directory="./chroma_handbook",
)
套件名稱會隨版本改;重點是這四步的順序,不要跳過 metadata。LlamaIndex 等價寫法是 SimpleDirectoryReader + VectorStoreIndex.from_documents。
載入時常見坑
- 雙欄 PDF、頁眉頁腳:抽出的文字順序錯亂,塊裡出現不相關的句子。必要時用版面解析(Azure Document Intelligence、LlamaParse 等)。
- 表格:切成散文後,欄位關係消失。重要表格可改成「一句話描述一列」再嵌入。
- 重複文件:同一份政策放在 wiki 與 PDF,檢索會佔滿 top-k。去重或合併來源。
何時重建
文件內容或切塊策略變了,就要重建或增量更新。只加新檔可以 upsert;改了嵌入模型則必須全量重算。把「語料版本」記在設定裡,評估時才知道數字對應哪一版索引。
下一頁:檢索。影片:LangChain Part 2 Indexing。