Gemma 嵌入搜尋
透過意義來檢索本地檔案。一個嵌入空間同時容納圖像、音頻和文字,因此輸入一個查詢即可傳回與之匹配的圖片、片段或文件。模型透過本地伺服器在使用者的硬體上執行;任何資料都不會上傳到別處。
scripts/embed_search.py 做了四件事:doctor 檢查伺服器,init 儲存連線,index 將檔案嵌入快取,search 根據查詢對它們進行排序。
本地設定
設定存放在 config.json 中,絕不在這個檔案中:
- Linux 和 macOS:
~/.config/gemma-embed-search/config.json - Windows:
%USERPROFILE%\.config\gemma-embed-search\config.json
請先讀取該檔案。如果它包含 url 和 model,則後續所有命令都可以在不使用連線旗標的情況下執行,並且可以跳過步驟 2。
如果該檔案遺失或不完整,請向使用者詢問伺服器 URL 和要索引的資料夾,執行 doctor 以列出伺服器實際提供的模型,然後執行 init 以寫入該檔案。init 會進行合併,因此一次只補充一個設定是安全的。切勿猜測模型名稱。
如果使用者更願意直接編輯檔案,將此資料夾中的 config.example.json 複製到該路徑並進行編輯,可以達到與 init 相同的效果。僅當伺服器需要時,才在其中加入 "api_key"。
切勿將設定儲存在技能資料夾本身內部。更新技能會取代其中的所有檔案,而寫入其中的任何內容都將遺失。
設定檢查清單
進度:
- 步驟 1:確認伺服器並選擇一個模型名稱(
doctor) - 步驟 2:儲存連線(
init) - 步驟 3:索引一個 20 檔案的測試集並快速檢視一個查詢
- 步驟 4:索引整個資料夾
- 步驟 5:回答使用者的真實查詢,並使用
--html以便他們能夠查看結果
如果 config.json 已經包含 url 和 model,則跳過步驟 2。
使用 uv run scripts/embed_search.py(會從腳本的內嵌元資料安裝 Pillow)或 python3 scripts/embed_search.py(如果 Pillow 已經可以匯入)來執行腳本。
步驟 1 — 找到伺服器和模型名稱。 切勿猜測模型名稱;請從伺服器讀取。
uv run scripts/embed_search.py --url http://127.0.0.1:1235 doctor
doctor 會列印伺服器提供的模型,並探測一個嵌入。如果使用者尚未啟動伺服器,請閱讀 references/setup.md 並為他們的模型提供命令。
步驟 2 — 儲存設定 以便後續呼叫無需使用旗標。僅在伺服器需要時傳遞 --api-key;它會以模式 0600 寫入設定檔。在任何後續命令中傳遞 --root 以對不同的資料夾進行操作,而不會更改已儲存的設定。
uv run scripts/embed_search.py --url http://127.0.0.1:1235 --model <name-from-doctor> init --root <folder>
uv run scripts/embed_search.py index --limit 20
步驟 3 — 在長時間執行前先進行測試。 索引是耗時的步驟:在桌上型 GPU 上每張影像約需 0.25 秒,因此 10,000 個檔案大約需要 40 分鐘。先索引 20 個檔案,執行一個查詢,並在進行完整處理前確認結果看起來正確。
步驟 4 — 完整索引。 重新執行 index 只會嵌入新增或變更的檔案,因此中斷的執行會自行恢復。
uv run scripts/embed_search.py index
步驟 5 — 搜尋。
uv run scripts/embed_search.py search "一隻在海灘上的黑色拉布拉多" --top 20 --html hits.html
查詢食譜
| 意圖 | 命令 |
|---|---|
| 純語義搜尋 | search "一個擁擠的夜市" |
| 兩個必須同時成立的面向 | search "一個女人" --must "黃色這個顏色" |
| 同義詞,避免單一措辭主導 | search "一個女人" --also "一個女孩" --also "女性肖像" |
| 找到包含 X 的每張圖片 | search "紅髮角色" --top 60 --html hits.html |
| 主題加上真實的顏色限制 | search "一個女人" --color yellow --min-color 0.05 |
| 主要是黑白或暗色調的畫面 | search "任何影像" --max-color blue --modality image |
| 僅一種類型的檔案 | search "警笛聲" --modality audio |
| 機器可讀格式,供後續使用 | search "..." --json --top 50 |
| 更快、略不精確的評分 | search "..." --dims 256 |
--also 將同義詞向量平均為一個查詢。--must 保留最弱面向的分數,這就是表達 AND 的方式。對同義詞使用 --also,對獨立條件使用 --must。
讀取輸出
純文字輸出為 分數 [模態] 路徑,最佳結果排在最前面。顏色執行會在分數後插入像素比例。--json 會輸出 {"query", "index", "total", "filtered_out", "results": [{"rank", "score", "color", "modality", "path"}]} 到標準輸出;所有進度訊息都會送到標準錯誤輸出,因此標準輸出始終可以乾淨地匯入 jq。
此模型家族的餘弦分數大約介於 0.3 到 0.8 之間。絕對數字意義不大;命中與未命中之間的差距才重要。如果列表頂部的結果是錯誤的,那麼查詢就是錯誤的——與其相信排序,不如重新表述查詢。切勿將一個長列表呈現為同樣優秀:請指出確信結果在哪裡結束,猜測從哪裡開始。
一個短列表並非完整答案。 每個索引的檔案都會得到一個分數,因此輸出中的 total 計算的是整個語料庫,絕不會告訴你有多少結果是合理的。請找出懸崖點——也就是分數停止急遽下降的那個點。如果你顯示的列表在該點之前就結束了,請說明結果已被截斷,並提供更長的執行:更大的 --top 只會多花一個聯絡表單的成本,而不是另一個索引。請尊重使用者指定的數量,但仍然說明你應用的截斷點。在沒有擴展列表(--top 100 或更多)且有人實際查看過的情況下,切勿聲稱「沒有結果」。
對於視覺審查,請始終提供 --html:它會寫入一個包含縮圖、分數和檔案名稱的聯絡表單,使用者可以在瀏覽器中開啟。單獨使用 --html 會在當前工作目錄寫入 hits.html;--html FILE 則設定路徑。縮圖會以 base64 嵌入,因此該表單是自我包含的,可以獨立傳遞。該表單嵌入了匹配檔案的真實縮圖,因此請將其視為該資料庫的一部分副本:請將其排除在版本控制之外,以及任何你轉發的內容之外。預設情況下,它們的寬度為 512 像素;若需仔細檢查細節,請提高 --thumb-width。
注意事項
- 查詢文字中的顏色詞是軟性提示,而不是篩選條件。
"一個黃色主題的女人"會先將一個穿著橘色夾克的女人排在前面。請使用--color yellow --min-color 0.05來實現實際的限制;它是從像素計算出來的,而不是從模型得出的。 - 風格詞也是軟性提示,而且更弱。
"一個紅髮的照片寫實風格女人"會先將一個紅髮女人的墨水插圖排在前面,因為主體名詞的權重超過了風格。將風格移到--must中,讓它作為自己的面向進行評分,並使用--color來固定視覺屬性。這兩者都不是真正的篩選條件:--must取所有面向的最小值,因此在一個方面用力會犧牲另一個方面。 - 一個畫面中的多個主體會混合成一個向量,因此該畫面在單一主體查詢中的得分會低於專門針對該主體的畫面:一個紅髮女人與一名男子並排的肖像,在
"紅髮女人"搜尋中可能會排在很後面,而在"紅髮角色"搜尋中則會接近頂部。同一單一概念的同義詞沒有幫助;複數或集體形式才有幫助。當問題是「找到包含 X 的所有東西」時,請加大--top。 --color需要索引包含顏色統計資料,而只有index會計算這些資料。使用舊版本建立的索引會為所有項目報告 0.0:如果顏色篩選默默地排除了所有檔案,請使用--force重新索引。- 索引和查詢必須使用相同的模型。切換
--model會默默地混合不相容的向量;在模型變更後,請使用--force重新索引,並在stats中註明模型。 - 伺服器必須載入具有平均池化及其視覺投影機(
--mmproj)的嵌入模型來執行。沒有投影機,影像請求會失敗,或傳回忽略圖片的向量。doctor證明文字有效;執行一個影像查詢來證明視覺功能。 - 影像在發送前會被重新編碼為 JPEG,長邊為 1536。重新編碼是必需的,而非裝飾性的:伺服器通常會拒絕 WebP、16 位元或標籤錯誤的檔案,而 Pillow 能夠讀取這些檔案。模型沒有像素限制——伺服器會將每張影像重新取樣到一個固定的視覺 token 預算——因此
--resize是在交換上傳大小與保真度,而非正確性。測量數字和詳細資訊請參閱 references/setup.md。 - 除非 Pillow 是使用外掛程式建置的,否則無法讀取 HEIC 和原始相機格式。腳本會記錄
skip <file>: cannot identify image file並繼續執行;請檢查索引摘要中的skipped_errors,而不是假設完全覆蓋。 - 對從未索引的資料夾執行
search會以訊息退出,代碼為 4。在stats中的索引計數看起來正確之前,不要將空結果列表視為「無匹配」。 - 音頻受到伺服器上下文的限制:在每秒 25 個 token 的情況下,每個片段約為 5.5 分鐘。較長的檔案會以請求錯誤的方式失敗,而不是作為不匹配的結果。
- 分數不能跨語料庫或跨量化級別進行比較。切勿承諾一個閾值;請根據使用者看到的結果來調整
--min-color和--top。
腳本參考
doctor 檢查伺服器,列出模型,探測一個嵌入
init [--root DIR] 將 url、model、key 和預設 root 儲存到設定檔
index --root DIR 嵌入新增和變更的檔案(增量,可恢復)
[--modality auto|image|audio|text] [--include '*.png,sub/*.jpg']
[--exclude-dir node_modules,.git] [--limit N] [--batch 16] [--resize 1536]
[--force] [--compact]
search "查詢" 對索引的檔案進行排序;列印分數、模態、路徑
[--also P]... [--must P]... [--color NAME --min-color F | --max-color F]
[--modality image] [--dims 512|256|128] [--top 20] [--offset 0]
[--json] [--html [FILE]] [--thumb-width 512]
stats 條目計數、模態混合、模型、索引大小
退出代碼:0 成功,2 使用錯誤,3 伺服器無法連線或驗證被拒絕,4 索引遺失,5 無事可做,6 伺服器執行中途錯誤。執行 scripts/embed_search.py <command> --help 以取得完整的旗標說明文件。
設定解析順序為 旗標 > 環境變數(EMBED_SEARCH_URL、EMBED_SEARCH_MODEL、EMBED_SEARCH_API_KEY、EMBED_SEARCH_ROOT)> 位於 ~/.config/gemma-embed-search/config.json 的設定檔。索引預設為 ~/.cache/gemma-embed-search/<folder>-<hash>.jsonl,每個檔案一個 JSON 記錄,因此為不同的資料夾維護多個索引是安全的。
更多詳細資訊
- references/setup.md — 啟動伺服器、模型和旗標要求、
doctor的含義 - references/query-guide.md — 查詢建構、面向邏輯、顏色閾值、根據真實結果進行調整
- references/errors.md — 每個退出代碼以及每種失敗模式的修復方法