Community影像github.com

claudejaune/gemma-embed-search

使用本地多模態嵌入模型索引圖像、音頻或文本資料夾,並以自然語言進行搜尋。透過任何相容於 OpenAI 的 /v1/embeddings 伺服器(例如執行 EmbeddingGemma 2 的 llama.cpp 的 llama-server)建立可恢復的向量索引,然後依據語義相似度對檔案進行排序,並支援顏色篩選、多面向 AND 查詢、JSON 輸出以及 HTML 聯絡表單……

gemma-embed-search 是什麼?

這個技能讓使用者能夠透過自然語言查詢,在本機硬體上對圖像、音頻和文本檔案進行語義搜尋。它會建立一個可恢復的向量索引,並使用任何相容於 OpenAI 的嵌入伺服器(例如 llama.cpp 的 llama-server)來執行。其核心程式碼 `scripts/embed_search.py` 包含 `doctor`(檢查伺服器狀態)、`init`(儲存連線設定)、`index`(將檔案嵌入快取)和 `search`(根據查詢對結果排序)等命令。設定是透過使用者家目錄中的 `config.json` 檔案進行管理,以確保更新技能時不會遺失任何設定。使用者可以透過多種參數來微調搜尋,例如 `--color` 用於顏色篩選、`--must` 用於多面向 AND 查詢、`--also` 用於同義詞擴展,以及 `--html` 用於產生包含縮圖的自我包含式聯絡表單。此技能支援檢查清單引導式設定、遞迴索引(支援增量與中斷後恢復),並提供詳盡的輸出結果,其中包含分數、檔案路徑以及可選的 JSON 格式資料。

相容平台✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/claudejaune/gemma-embed-search/tree/HEAD

Installed? Explore more 影像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

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 記錄,因此為不同的資料夾維護多個索引是安全的。

更多詳細資訊

相關技能