CommunityImagemgithub.com

Gemma Embed Search

Indexeie uma pasta de imagens, áudio ou texto com um modelo local de embeddings multimodais e faça buscas em linguagem natural. Cria um índice vetorial retomável através de qualquer servidor compatível com OpenAI /v1/embeddings que aceite partes multimodais, como o llama-server do llama.cpp executando o EmbeddingGemma 2, e classifica arquivos por similaridade semântica com filtragem por cor, consultas AND multifacetadas, saída JSON e folha de contatos HTML.

O que é Gemma Embed Search?

A habilidade Gemma Embed Search permite que você busque arquivos locais (imagens, áudio e texto) com base em seu significado, usando um modelo de embeddings multimodal executado localmente. Ela cria um índice vetorial incremental e retomável, onde uma única consulta em linguagem natural pode retornar os arquivos mais relevantes, independentemente do tipo de mídia. O sistema suporta filtragem por cor (com base nos pixels reais), consultas lógicas AND com múltiplas facetas usando `--must`, sinônimos com `--also`, e saída em JSON ou HTML (com miniaturas base64). Tudo roda localmente, sem upload de dados. A ferramenta é útil para desenvolvedores que precisam pesquisar grandes coleções de mídia local, prototipar sistemas RAG ou organizar arquivos não textuais como imagens e clipes de áudio. Os principais comandos incluem `doctor` (verifica o servidor), `init` (salva a configuração), `index` (processa arquivos incrementalmente) e `search` (consulta o índice com várias opções de refinamento). A configuração é feita por arquivo `config.json` e flags de linha de comando, com suporte a variáveis de ambiente para URL, modelo, chave API e pasta raiz.

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

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que Gemma Embed Search faz?

Recupere arquivos locais pelo significado. Um único espaço de embeddings guarda imagens, áudio e texto, de modo que uma consulta digitada retorna as fotos, clipes ou documentos que correspondem a ela. O modelo é executado no hardware do usuário por meio de um servidor local; nada é enviado para lugar nenhum.

scripts/embed_search.py faz quatro coisas: doctor verifica o servidor, init salva a conexão, index incorpora arquivos em um cache, e search os classifica em relação a uma consulta.

Configuração local

As configurações ficam em config.json, nunca neste arquivo:

  • Linux e macOS: ~/.config/gemma-embed-search/config.json
  • Windows: %USERPROFILE%\.config\gemma-embed-search\config.json

Leia esse arquivo primeiro. Se ele contiver url e model, todos os comandos subsequentes funcionam sem as flags de conexão e você pode pular a Etapa 2.

Se estiver faltando ou incompleto, peça ao usuário a URL do servidor e a pasta a ser indexada, execute doctor para listar os modelos que o servidor realmente oferece e depois execute init para escrever o arquivo. init faz merge, então adicionar uma configuração de cada vez é seguro. Nunca adivinhe um nome de modelo.

Copiar config.example.json desta pasta para aquele caminho e editá-lo faz o mesmo trabalho que init, para um usuário que prefere editar o arquivo diretamente. Adicione "api_key" lá apenas se o servidor precisar de uma.

Nunca salve configurações dentro da própria pasta da habilidade. Atualizar a habilidade substitui todos os arquivos nela, e qualquer coisa escrita ali será perdida.

Checklist de configuração

Progresso:

  • Etapa 1: Confirme o servidor e escolha um nome de modelo (doctor)
  • Etapa 2: Salve a conexão (init)
  • Etapa 3: Indexe um piloto de 20 arquivos e verifique uma consulta
  • Etapa 4: Indexe a pasta inteira
  • Etapa 5: Responda à consulta real do usuário, com --html para que ele possa ver os resultados

Pule a Etapa 2 se config.json já tiver url e model.

Execute o script com uv run scripts/embed_search.py (instala o Pillow a partir dos metadados inline do script) ou python3 scripts/embed_search.py se o Pillow já estiver importável.

Etapa 1 — encontre o servidor e o nome do modelo. Nunca adivinhe o nome do modelo; leia-o do servidor.

uv run scripts/embed_search.py --url http://127.0.0.1:1235 doctor

doctor imprime os modelos que o servidor oferece e testa um embedding. Se o usuário ainda não iniciou um servidor, leia references/setup.md e dê a eles o comando para o modelo deles.

Etapa 2 — salve para que chamadas posteriores não precisem de flags. Passe --api-key apenas se o servidor exigir uma; ela é escrita no arquivo de configuração com modo 0600. Passe --root em qualquer comando posterior para trabalhar em uma pasta diferente sem alterar o que foi salvo.

uv run scripts/embed_search.py --url http://127.0.0.1:1235 --model <nome-do-doctor> init --root <pasta>
uv run scripts/embed_search.py index --limit 20

Etapa 3 — piloto antes da execução longa. A indexação é a etapa cara: aproximadamente 0,25 s por imagem em uma GPU de desktop, então 10.000 arquivos são cerca de 40 minutos. Indexe 20 arquivos, execute uma consulta, e confirme se os resultados parecem corretos antes de se comprometer com a passagem completa.

Etapa 4 — índice completo. Reexecutar index apenas incorpora arquivos novos ou alterados, então uma execução interrompida é retomada automaticamente.

uv run scripts/embed_search.py index

Etapa 5 — busca.

uv run scripts/embed_search.py search "um labrador preto na praia" --top 20 --html hits.html

Livro de receitas de consultas

IntençãoComando
Busca semântica simplessearch "um mercado noturno lotado"
Duas facetas que devem ser verdadeirassearch "uma mulher" --must "a cor amarela"
Sinônimos para que uma frase não dominesearch "uma mulher" --also "uma garota" --also "retrato feminino"
Encontrar toda imagem contendo Xsearch "personagens com cabelo ruivo" --top 60 --html hits.html
Sujeito mais restrição real de corsearch "uma mulher" --color yellow --min-color 0.05
Quadros quase monocromáticos ou escurossearch "qualquer imagem" --max-color blue --modality image
Apenas um tipo de arquivosearch "sons de sirene" --modality audio
Legível por máquina para trabalho posteriorsearch "..." --json --top 50
Mais rápido, pontuação ligeiramente menos precisasearch "..." --dims 256

--also calcula a média dos vetores de paráfrase em uma única consulta. --must mantém a pontuação da faceta mais fraca, que é como você expressa AND. Use --also para sinônimos e --must para condições independentes.

Lendo a saída

A saída simples é pontuação [modalidade] caminho, melhores primeiro. Execuções com cor inserem a proporção de pixels após a pontuação. --json emite {"query", "index", "total", "filtered_out", "results": [{"rank", "score", "color", "modality", "path"}]} na saída padrão; todo o progresso vai para o stderr, então a saída padrão sempre pode ser canalizada diretamente para jq.

As pontuações de cosseno desta família de modelos ficam entre aproximadamente 0,3 e 0,8. O número absoluto significa pouco; a diferença entre acertos e erros importa. Se o topo da lista estiver errado, a consulta está errada — reformule-a em vez de confiar na classificação. Nunca apresente uma lista longa como igualmente boa: indique onde os resultados confiantes param e os palpites começam.

Uma lista curta não é a resposta completa. Cada arquivo indexado recebe uma pontuação, então o total na saída conta todo o corpus e nunca informa quantos resultados são plausíveis. Encontre o precipício — o ponto onde as pontuações param de cair abruptamente. Se a lista que você mostrou terminar antes dele, diga que os resultados foram truncados e ofereça uma execução mais longa: um --top maior custa apenas mais uma folha de contatos, não outra indexação. Respeite um número que o usuário nomear e ainda declare o corte que você aplicou. Nunca afirme "não há nenhum" sem uma lista ampliada, --top 100 ou mais, que alguém tenha realmente examinado.

Para revisão visual, sempre ofereça --html: ele escreve uma folha de contatos de miniaturas com pontuações e nomes de arquivo que o usuário pode abrir em um navegador. Um --html simples escreve hits.html no diretório de trabalho; --html ARQUIVO define o caminho. As miniaturas são incorporadas como base64, então a folha é autocontida e viaja sozinha. A folha incorpora miniaturas reais dos arquivos correspondentes, então trate-a como uma cópia dessa parte da biblioteca: mantenha-a fora do controle de versão e fora de qualquer coisa que você encaminhe. Elas têm 512 px de largura por padrão; aumente --thumb-width para inspeção detalhada.

Pegadinhas

  • Uma palavra de cor dentro do texto da consulta é uma dica suave, não um filtro. "uma mulher com tema amarelo" classifica uma mulher com jaqueta laranja em primeiro lugar. Use --color yellow --min-color 0.05 para uma restrição real; ela é calculada a partir dos pixels, não do modelo.
  • Uma palavra de estilo também é uma dica suave, e mais fraca. "uma mulher fotorrealista com cabelo ruivo" classifica uma ilustração a tinta de uma mulher ruiva em primeiro lugar, porque os substantivos do sujeito superam o estilo. Mova o estilo para --must para que seja pontuado como sua própria faceta e fixe o atributo visual com --color. Nenhum dos dois é um filtro verdadeiro: --must pega o mínimo entre as facetas, então forçar muito em uma troca a outra.
  • Vários sujeitos em um quadro se misturam em um único vetor, então o quadro pontua pior em uma consulta de sujeito único do que um quadro dedicado àquele sujeito: um retrato de uma mulher ruiva ao lado de um homem pode ficar bem abaixo em uma busca por "mulher com cabelo ruivo" enquanto está no topo de "personagens com cabelo ruivo". Sinônimos da mesma ideia singular não ajudam; a forma plural ou coletiva sim. Aumente --top quando a pergunta for "encontrar tudo que contém X".
  • --color precisa que o índice tenha estatísticas de cor, que só o index calcula. Um índice construído com uma versão antiga informa 0.0 para tudo: reindexe com --force se o filtro de cor excluir silenciosamente todos os arquivos.
  • Índice e consulta devem usar o mesmo modelo. Trocar --model mistura silenciosamente vetores incompatíveis; reindexe com --force após qualquer alteração de modelo e anote o modelo em stats.
  • O servidor deve executar o modelo de embedding com pooling médio e seu projetor de visão (--mmproj) carregado. Sem o projetor, as requisições de imagem falham ou retornam um vetor que ignora a imagem. doctor prova que o texto funciona; execute uma consulta de imagem para provar a visão.
  • As imagens são recodificadas para JPEG com o lado maior em 1536 antes de serem enviadas. A recodificação é necessária, não cosmética: servidores comumente rejeitam WebP, 16 bits ou arquivos com rótulo incorreto, e o Pillow lê esses em vez disso. O modelo não tem limite de pixels — o servidor reamostra cada imagem para um orçamento fixo de tokens de visão — então --resize troca o tamanho do upload pela fidelidade, não pela correção. Números medidos e detalhes estão em references/setup.md.
  • Formatos HEIC e raw de câmera não são lidos a menos que o Pillow tenha sido construído com o plugin. O script registra skip <arquivo>: cannot identify image file e continua; verifique skipped_errors no resumo da indexação em vez de assumir cobertura total.
  • search em uma pasta que nunca foi indexada sai com código 4 e uma mensagem. Não trate uma lista de resultados vazia como "sem correspondências" até que a contagem do índice em stats pareça correta.
  • O áudio é limitado pelo contexto do servidor: cerca de 5,5 minutos por clipe a 25 tokens por segundo. Arquivos mais longos falham como um erro de requisição, não como uma correspondência ruim.
  • As pontuações não são comparáveis entre corpora ou entre quantizações. Nunca prometa um limite; ajuste --min-color e --top com base no que o usuário vê.

Referência do script

doctor                       Verifica o servidor, lista modelos, testa um embedding
init [--root DIR]            Salva url, modelo, chave e raiz padrão no arquivo de configuração
index   --root DIR           Incorpora arquivos novos e alterados (incremental, retomável)
        [--modality auto|image|audio|text] [--include '*.png,sub/*.jpg']
        [--exclude-dir node_modules,.git] [--limit N] [--batch 16] [--resize 1536]
        [--force] [--compact]
search  "consulta"            Classifica arquivos indexados; imprime pontuação, modalidade, caminho
        [--also P]... [--must P]... [--color NOME --min-color F | --max-color F]
        [--modality image] [--dims 512|256|128] [--top 20] [--offset 0]
        [--json] [--html [ARQUIVO]] [--thumb-width 512]
stats                        Contagem de entradas, mistura de modalidades, modelo, tamanho do índice

Códigos de saída: 0 sucesso, 2 erro de uso, 3 servidor inacessível ou autenticação rejeitada, 4 índice ausente, 5 nada a fazer, 6 erro do servidor durante a execução. Execute scripts/embed_search.py <comando> --help para documentação completa das flags.

A resolução de configuração é flag > ambiente (EMBED_SEARCH_URL, EMBED_SEARCH_MODEL, EMBED_SEARCH_API_KEY, EMBED_SEARCH_ROOT) > arquivo de configuração em ~/.config/gemma-embed-search/config.json. O índice padrão é ~/.cache/gemma-embed-search/<pasta>-<hash>.jsonl, um registro JSON por arquivo, então é seguro manter vários índices para pastas diferentes.

Mais detalhes

Habilidades Relacionadas