Vector#
Rotas
/v1/cloudvec/*· owner/admin · gated porCLOUDVEC_ENABLED(off → 404)
O que é#
Busca semântica gerenciada (RAG) sobre seus textos e documentos. Você cria coleções, coloca documentos (ou sobe arquivos que o sistema converte + chunka + indexa), e busca por significado — não por palavra-chave. Por baixo: embeddings da OpenAI + PostgreSQL/pgvector.
O que dá pra fazer#
- Criar/listar/remover coleções (por projeto).
- Organizar em pastas hierárquicas (
suporte/faturamento/) e escopar a busca por pasta (recursivo). - Adicionar documentos por texto (embeda + upserta em lote, até 100/request).
- Ingerir qualquer arquivo (PDF, docx, xlsx, pptx, imagens, md, txt…): o pipeline converte para Markdown, guarda original + Markdown no Storage, chunka e embeda. Imagens e PDFs escaneados passam por OCR via visão.
- Buscar por similaridade de cosseno, escopada por pasta; resultados de arquivos apontam de volta para a fonte.
Como funciona por dentro (na prática)#
- Coleção = control-row + tabela de vetores. Cada coleção é uma linha no tenant
DB (
vec_collections) + uma tabela no pgvector (namespaced peloidda coleção). - Embedder por-coleção. O modelo de embedding fica gravado em cada coleção
(default para novas:
text-embedding-3-large, 3072 dims; coleções antigas3-small/1536 continuam funcionando — modelos coexistem). A busca embeda a query com o modelo da coleção e compara com<=>(cosine distance) no pgvector. - Pastas = caminho materializado. Cada documento tem um
path. A busca é por prefixo, recursiva: sempathbusca tudo;path:"suporte/"buscasuporte/- subpastas. Só documentos reais entram (placeholders de pasta vazia são excluídos).
- Ingestão (fontes). Um arquivo → sidecar MarkItDown (+ passe opcional de
embelezamento OpenAI) → Storage guarda original +
.mdespelhando a árvore de pastas (vector/<coleção>/<pasta><arquivo>) → o Markdown é quebrado em chunks embedados. Imagens/PDF escaneado → OCR de visão (modelogpt-5.4-mini,detail:high, prompt de fidelidade que não inventa valores). Cada arquivo vira uma fonte (VecSource) rastreável; seus chunks não inflam odocument_countnem aparecem noGET /documents— ficam no card da fonte, e carregammetadata.source_filename/source_idpara o resultado apontar de volta. - Busca híbrida e re-rank. Além do cosine puro, a busca aceita fusão
híbrida (semântica + lexical via RRF) para não perder termo exato, re-rank
LLM opt-in, filtros por metadata/fonte/tipo e modos de retrieval com FAQ
cards (
qa_first). Detalhes na seção Busca abaixo.
Fluxo típico (end-to-end)#
KEY="X-API-Key: ctc_…" ; B=https://data-api.catcher.one ; JS='Content-Type: application/json'
PID=<project-uuid>
# 1. Cria a coleção (tenant_id é opcional — isola um cliente final; ver Tenants)
CID=$(curl -sX POST $B/v1/cloudvec/projects/$PID/collections -H "$KEY" -H "$JS" \
-d '{"name":"docs"}' | jq -r .id)
# 2a. Adiciona documentos por texto (embeda em lote)
curl -sX POST $B/v1/cloudvec/collections/$CID/documents -H "$KEY" -H "$JS" -d '{
"documents":[{"content":"O servidor tem 12 meses de garantia.","path":"suporte/","metadata":{"src":"faq"}}]}'
# 2b. …ou sobe um arquivo (converte → Storage → chunka → embeda; assíncrono)
curl -sX POST $B/v1/cloudvec/collections/$CID/ingest -H "$KEY" \
-F "file=@./manual.pdf" -F "path=suporte/"
# → { "id":"…","status":"processing","chunk_count":…,"filename":"manual.pdf" }
# 3. Busca semântica (escopada por pasta, recursiva)
curl -sX POST $B/v1/cloudvec/collections/$CID/search -H "$KEY" -H "$JS" \
-d '{"query":"quanto tempo de cobertura contra defeitos?","k":5,"path":"suporte/"}'
# → { "results":[{"id","content","metadata","score"}], "count":5 }
Referência de endpoints#
Coleções#
| Método | Rota | O que faz |
|---|---|---|
POST |
/v1/cloudvec/projects/{pid}/collections |
Cria ({name} lowercase 2-48, tenant_id?) → 201 (embed_model, dimensions, tenant_id?) |
GET |
/v1/cloudvec/projects/{pid}/collections |
Lista |
GET |
/v1/cloudvec/collections/{id} |
Detalhe + document_count vivo |
DELETE |
/v1/cloudvec/collections/{id} |
Remove (dropa tabela de vetores + control-row) → 204 |
Isolamento por tenant (end-customers)
Passe tenant_id ao criar a coleção para isolar um cliente final: a coleção
passa a viver no schema Postgres dedicado do tenant (t_<id> + role tr_<id>)
e a busca naquela coleção só enxerga os vetores dele. Sem tenant_id, a coleção é
de nível projeto (schema default public, compartilhada). É o mesmo tenant_id
usado no Database, Storage e Cache — ver Tenants. Para isolar
ainda mais fino (por usuário final dentro de um tenant) sem multiplicar coleções,
use o filter por metadata na busca (abaixo).
Pastas#
| Método | Rota | O que faz |
|---|---|---|
POST |
/v1/cloudvec/collections/{id}/folders |
Cria pasta ({path}) → 201 {path:"suporte/faturamento/"} |
GET |
/v1/cloudvec/collections/{id}/folders?parent= |
Subpastas imediatas |
GET |
/v1/cloudvec/collections/{id}/folders/stats?path= |
{document_count} recursivo |
DELETE |
/v1/cloudvec/collections/{id}/folders?path= |
Apaga pasta + conteúdo recursivo → {deleted:N} |
Documentos#
| Método | Rota | O que faz |
|---|---|---|
POST |
/v1/cloudvec/collections/{id}/documents |
Embeda + upserta ({documents:[{content,path?,id?,metadata?}]}, máx. 100) → 201 |
GET |
/v1/cloudvec/collections/{id}/documents?path=&recursive=&limit= |
Lista (limit ≤ 1000) |
DELETE |
/v1/cloudvec/collections/{id}/documents/{docId} |
Remove → 204 |
Busca#
POST /v1/cloudvec/collections/{id}/search →
{results:[{id,content,metadata,score}], count}
| Campo | Tipo | O que faz |
|---|---|---|
query |
string | A consulta (é embedada — 1 embedding por busca). |
k |
int | Máximo de resultados (default 5). |
path |
string | Escopo por pasta, recursivo (""/ausente = coleção inteira). |
hybrid |
bool | Fusão RRF do braço semântico (cosine) com um braço lexical full-text ANTES do corte top-k — um doc term-exato (ID, SKU, código) que o cosine enterrou ainda aparece. Cada hit ganha metadata.match: "semantic"|"lexical"|"both". |
alpha |
float 0..1 | Peso do braço semântico na fusão (lexical = 1−alpha; ausente = 0.5; 0 = lexical puro). |
rerank |
bool | Re-rank listwise com LLM após a recuperação (opt-in — custa uma chamada de modelo; use em consultas críticas). |
mode |
string | Retrieval com FAQ cards do Refinery: default qa_first (cards antes de chunks; degrada para chunks se não houver cards) · chunks (só chunks) · qa_only. |
filter |
map | Pré-filtro de igualdade por metadata (AND), ex.: {"end_user_id":"u_9"}. |
source_id |
string | Só chunks de uma fonte específica. |
type |
string | Só um tipo de fonte (pdf|word|spreadsheet|markdown|text|…). |
score = similaridade de cosseno em [0,1] (1 = idêntico).
Ingestão de arquivos (fontes)#
| Método | Rota | O que faz |
|---|---|---|
POST |
/v1/cloudvec/collections/{id}/ingest |
Multipart (file + path?), ≤ 64 MB → {id,status:"processing",chunk_count,…} |
GET |
/v1/cloudvec/collections/{id}/sources?path= |
Lista fontes em path |
GET |
/v1/cloudvec/collections/{id}/sources/{sid} |
Detalhe + signed URLs (TTL 30 min) do original + Markdown + os chunks |
DELETE |
/v1/cloudvec/collections/{id}/sources/{sid} |
Remove fonte + chunks + objetos no Storage → 204 |
Ingestão de binários requer o sidecar (CLOUDVEC_CONVERTER_URL) + CLOUDSTORE_ENABLED + um GCP project READY no projeto (para o bucket vector-sources). .md/.txt passam direto.
Códigos de erro do módulo#
INVALID_COLLECTION_NAME (400, inclui path inválido) · COLLECTION_ALREADY_EXISTS
(409) · COLLECTION_NOT_FOUND (404) · EMPTY_INPUT (400) · BATCH_TOO_LARGE (400,
100 docs) ·
EMBEDDING_DIMENSION_MISMATCH(400) ·SOURCE_NOT_FOUND(404) ·CONVERSION_UNAVAILABLE(422, sidecar ausente p/ binário) ·NO_READY_PROJECT(409) ·MISSING_FIELD(400).
Gotchas#
- Embeddings custam (OpenAI) —
documentscobra por embedar cadacontent; busca cobra 1 embedding por query. Agrupe inserções em lote (até 100/request). - Não misture modelos numa coleção — o modelo é fixado na criação; se mudar o
default global, coleções novas usam o novo, as antigas mantêm o seu (sem
EMBEDDING_DIMENSION_MISMATCH). - Ingestão é assíncrona —
status: processing→ready|failed(last_error); faça poll viaGET .../sources/{sid}. - Chunks de fontes ≠ documents — não aparecem no
GET /documentsnem contam nodocument_count; aparecem nos resultados de busca commetadata.source_filename. - Para RAG: ingira os docs em pastas por assunto, depois
searchcompathpara focar o contexto ekpara o tamanho do contexto.