大多數向量資料庫的原型在資料匯入階段就失敗了,而不是在搜尋階段。你構建了一個巧妙的檢索管道,看著它在數千個文件上工作,然後有人遞給你五千萬行資料。接下來的兩週你將陷入速率限制、部分失敗以及三次重寫批處理邏輯的泥潭。
本文是我希望自己在第一次將真實資料集匯入 Weaviate 時就能擁有的指南。它涵蓋了服務端批處理、錯誤處理、那些一旦選錯就會讓你付出最大代價的資料型別決策,以及如何在不搭建 OCR 管道的情況下攝入媒體和 PDF。
沒有人警告過你的匯入問題
一個能用的原型無法告訴你大規模執行時會發生什麼。那些困擾生產團隊的問題幾乎從未在教程中出現過。四個最棘手的問題:
- 嵌入提供商的速率限制:大多數團隊在真正匯入後一小時內就會遇到,然後寫重試程式碼,再為重試程式碼寫重試程式碼。
- HTTP 200 的謊言:成功的批處理響應並不代表每個物件都已寫入。單個物件可能在綠色狀態碼背後悄然失敗。
- 重試時的重複工作:如果你每次重新執行都生成新的 ID,你會重新向量化相同的文件併為此支付兩次費用。
- 媒體檔案的記憶體爆炸:將一百萬個產品照片載入到 Python 列表會在批處理邏輯執行之前就終結你的指令碼。
服務端批處理
服務端批處理是一種流式匯入模式,Weaviate 伺服器會根據自身當前的工作負載告訴客戶端接下來應傳送多少資料。你無需猜測批次大小和併發級別,伺服器會測量其佇列深度並透過持久連線施加背壓。
這很重要,因為正確的批次大小不是一個常數。它取決於你擁有的屬性數量、文本欄位的大小、是否即時向量化、向量化器在底層做什麼以及叢集的其他負載。手動調整很脆弱。伺服器已經擁有所有這些資訊。
以下是 Python 客戶端中的模式:
import weaviate
from weaviate.classes.init import Auth
client = weaviate.connect_to_weaviate_cloud(
cluster_url=WCD_URL,
auth_credentials=Auth.api_key(WCD_API_KEY),
)
collection = client.collections.get("Products")
with collection.batch.stream() as batch:
for row in iter_rows():
batch.add_object(properties=row)
if batch.number_errors > 10:
print("錯誤過多,停止。")
break
if collection.batch.failed_objects:
print(f"{len(collection.batch.failed_objects)} 個物件失敗。")這就是整個模式。沒有 batch_size,沒有 concurrent_requests,沒有調優。stream() 上下文管理器開啟持久連線,伺服器設定速率,錯誤非同步流回而不會中斷流程。
錯誤處理與重試
生產環境中匯入指令碼最常見的錯誤是將 200 響應視為成功的證明。事實並非如此。200 表示你的請求到達伺服器並被接受,但並不代表每個物件都已被寫入。向量化器錯誤、模式不匹配以及上游嵌入 API 的速率限制響應都會作為逐物件錯誤出現在一個原本正常的批處理響應中。
Python 客戶端會在每次批處理中公開三件事:
- batch.failed_objects:每個失敗的物件及錯誤資訊
- batch.failed_references:每個失敗的交叉引用
- batch.number_errors:上下文管理器內的執行計數
將 failed_objects 視為一個佇列。將其寫入檔案,重試,如果同一錯誤再次失敗,則將其移至死信位置,這樣其餘部分的匯入就不會因一個損壞的行而停滯。
以下是一個在生產中經得起考驗的重試+檢查點模式:
import json
from weaviate.util import generate_uuid5
with collection.batch.stream() as batch:
for row in iter_rows():
batch.add_object(
properties=row,
uuid=generate_uuid5(row["source_id"]),
)
with open("failed.jsonl", "a") as f:
for obj in collection.batch.failed_objects:
f.write(json.dumps({
"properties": obj.object_.properties,
"error": obj.message,
}) + "\n")有兩件事使得這個模式可以安全地重新執行。首先,generate_uuid5 對相同的 source_id 產生相同的 UUID,因此重試會覆蓋而不是重複。其次,錯誤會被寫入一個檔案,你可以在修復根本問題後重新匯入該檔案。沒有靜默丟失,也沒有嵌入的雙重計費。
常見失敗模式及應對措施:
| 症狀 | 可能原因 | 修復 | |------|----------|------| | HTTP 200,物件缺失 | 向量化器速率受限 | 檢查 failed_objects,重試失敗子集 | | 客戶端記憶體爆炸 | 在流式傳輸前載入整個資料集 | 從磁碟或資料庫游標流式讀取,不要預載入 | | 重試後出現重複物件 | 每次執行使用新鮮的隨機 UUID | 使用基於穩定源鍵的 generate_uuid5 | | 匯入後向量為空 | 集合上未配置向量化器模組 | 重新執行前檢查集合配置 |
透過 MCP 伺服器匯入
Weaviate 內建了一個 MCP 伺服器(預覽版,v1.37.1 新增),允許 LLM 或 IDE 助手(如 Claude Code、Cursor、VS Code)透過模型上下文協議讀寫你的例項。啟用 MCP_SERVER_ENABLED=true,並選擇啟用寫入(MCP_SERVER_WRITE_ACCESS_ENABLED=true),伺服器會暴露一個 weaviate-objects-upsert 工具,允許在對話中建立或更新物件。它執行在與 REST API 相同的埠上,並尊重 RBAC,因此無需額外部署。
當代理需要在工作時寫入少量記錄時(持久化代理記憶、同步小型集合或在編輯器中修復少量物件),這是正確的工具。
但它不是匯入管道。每個物件都是由模型組裝並透過工具呼叫傳遞的,因此受限於上下文視窗和每次呼叫的延遲,且沒有上述章節中的背壓、流式或重試檢查點機制。超過幾十個物件後,請使用 collection.batch.stream()(或客戶端的批處理 API),將 MCP 伺服器留給它擅長的小批次對話式寫入。
匯入前選擇資料型別
模式決策在匯入執行後修復的成本要高出十倍。第一次就做對。
在匯入時最重要的決策:
- 使用正確分詞法的 text。分詞法決定了哪些 BM25 查詢匹配哪些記錄。對於英文散文,預設值很好。對於產品程式碼、URL 或任何字面字串重要的內容,請切換為欄位分詞。分詞教程介紹了權衡。
- 用於外部索引鍵的 uuid。索引後用於快速過濾,在插入時驗證,並在客戶端中作為真正的 UUID 呈現,而不是字串。
- int 與 number。對於計數和 ID 使用 int,對於價格和比率使用 number。混用會在每個查詢中強制進行型別轉換。
- 對於實際過濾的關係,使用引用型別。如果要獨立查詢相關欄位,不要將所有內容都展平到一個大型巢狀物件中。
完整列表在資料型別參考中。
blobHash:儲存嵌入,跳過位元組
如果你正在匯入媒體(影像、音訊、影片、PDF),這是需要了解的資料型別。
常規 blob 將完整的 base64 有效負載儲存在磁碟上。blobHash 則不然。它在匯入時將原始位元組傳送給向量化器,以便模型看到實際媒體,然後丟棄除 SHA-256 雜湊之外的所有內容。向量索引保留嵌入。blob 儲存保留一個 32 位元組的指紋。
{
"properties": [
{
"name": "product_image",
"dataType": ["blobHash"]
}
]
}實際影響:一個 10 TB 的影像語料庫會縮減為幾 GB 的雜湊加上向量索引。相似性搜尋的行為與使用 blob 完全相同。你只是不需要在 Weaviate 中儲存原始位元組。將它們儲存在應有的物件儲存中。
還有另一個不錯的特性。當你更新一個物件時,新的 base64 會被雜湊並與儲存的雜湊進行比較。如果雜湊匹配,Weaviate 會完全跳過重新向量化。僅此一點就能在有人錯誤地重新執行匯入管道時收回成本。
無需 OCR 管道的 PDF 向量化
對於大多數讀者來說,實際問題是“如何在不編寫 OCR 管道的情況下匯入 PDF 資料夾。”最簡短的答案是啟動 Weaviate Cloud 試用版並使用 Weaviate Embeddings。
Weaviate Embeddings 有一個專為基於影像的文件檢索設計的多模態模型。你給它一個頁面影像,它會生成一個向量。無需 OCR 步驟。無需佈局檢測。無需文本提取。表格、圖表、掃描表單、混合語言文件都以相同的方式處理。這是僅雲端方案,但它是嘗試在真實資料集上進行 PDF 檢索的最簡單途徑,對於數十萬頁以內的集合,無需你做任何架構決策。
另一個現成選項是 Google 的 multi2vec-google(與 gemini-embedding-2 搭配,3072 維),在 Weaviate Cloud 上預設啟用。它遵循相同的工作流程:你將頁面渲染為影像並嵌入這些影像。該模組接受影像輸入,而非原始 PDF 檔案,因此柵格化步驟與 Weaviate Embeddings 相同。
如果你在規模上自行託管且文件佈局很重要,請檢視多向量 ColPali 配方。它使用視覺語言模型為每頁生成多個向量,並完全跳過分塊。元件更多,但對於視覺豐富文件的檢索而言,這是最先進的技術。
所有三種方案都在同一位置——模型提供商參考中。
多模態匯入:文本、影像、音訊、影片
Weaviate 中的多模態並非獨立產品。它是集合上的一個向量化器模組。你宣告集合使用哪個模型,匯入具有媒體屬性(理想情況下為 blobHash)的物件,並使用你已有的同一客戶端跨模態查詢。
各提供商覆蓋範圍:
| 提供商 | 模組 | 文本 | 影像 | 音訊 | 影片 | |--------|------|------|------|------|------| | Weaviate Embeddings | native (WCD) | ✓ | ✓ | | | | Google | multi2vec-google | ✓ | ✓ | ✓ | ✓ | | Voyage AI | multi2vec-voyageai | ✓ | ✓ | ✓ | | | Jina AI | multi2vec-jinaai | ✓ | ✓ | | | | Cohere | multi2vec-cohere | ✓ | ✓ | | | | NVIDIA | multi2vec-nvidia | ✓ | ✓ | | | | CLIP (self-hosted) | multi2vec-clip | ✓ | ✓ | | | | ImageBind (self-hosted) | multi2vec-bind | ✓ | ✓ | | |
一個具體場景:你正在為電商目錄構建搜尋。每個產品都有名稱、描述、三張照片和一個十五秒的演示影片。你想要一個查詢——“緊湊型無線耳塞,帶主動降噪”——來找到正確的產品,無論相關訊號在文本、照片還是影片中。
你宣告一個集合,該集合在命名向量上使用 multi2vec-google:一個用於名稱和描述的文本向量,加上一個用於產品影像的獨立 blobHash 向量,以及另一個用於演示影片的向量。每個 blobHash 屬性都需要自己的命名向量——一旦 Weaviate 將原始位元組替換為雜湊,它們就無法再與其他欄位一起重新向量化,因此模式將它們分開。然後,一個多目標查詢同時對所有三個向量進行排名:一個集合,一個查詢,三種模態——而且媒體位元組永遠不會在 Weaviate 內部儲存兩次。
每個提供商的完整設定細節都在模型提供商參考中。
開始前的檢查清單
- 仔細選擇資料型別。任何不需要檢索原始資料的媒體使用 blobHash。任何字面字串重要的文本使用欄位分詞。
- 在集合級別選擇向量化器,而不是在匯入指令碼中。在 Weaviate Cloud 上,Weaviate Embeddings 是最簡單的預設選項。
- 使用確定性 UUID(從穩定源鍵生成 generate_uuid5),以便重試具有冪等性。
- 使用服務端流式批處理,避免手動調整批次大小。
- 實現死信佇列以處理永續性錯誤。
- 對於多模態內容,使用 blobHash 並配置帶有獨立命名向量的多模態模型。