O mecanismo · 0.1.0b4

Uma consulta ao diretório.
Uma varredura contígua.

A busca vetorial filtrada é geralmente um scatter-gather por um índice que nada sabe sobre seu filtro. O Telys controla o layout físico: na chave de partição, vizinhos-mais-próximos-onde-chave-igual-a-x é uma consulta O(1) ao diretório mais uma varredura sequencial de um bloco contíguo. Esta página percorre o runtime em produção hoje e, em seguida, a arquitetura para a qual ele está convergindo — rotulada como spec.

Painel 01 · Hoje — o runtime em produção
01 Layout físico

A engine controla onde cada vetor reside.

Uma collection declara partition_by na criação, e o layout segue a chave. O segmento base é clusterizado por partição — cada chave mapeia para uma fatia contígua — e escritas recentes ficam ao lado em um delta mutável com formato Arrow.

Segmento base

Clusterizado por partição

Vetores armazenados ordenados por chave de partição, de modo que cada partição é um bloco contíguo. Uma consulta com escopo lê uma sequência contínua de memória, não linhas dispersas por um índice.

Diretório de partições

O(1) chave → fatia

Um diretório mapeia cada valor de partição ao seu (offset, length) no segmento base. Resolver o filtro é uma consulta ao dicionário, não uma travessia de índice.

Delta mutável

Escritas com formato Arrow

add e upsert acrescentam aqui, cada linha marcada com um LSN de escrita monotônico. O delta é consultável imediatamente e se une à fatia base por um único caminho de varredura.

02 O caminho de leitura

O que uma consulta com escopo executa.

Consulta

col.search(qvec, where={"tenant_id": "acme"}, top_k=10)

O filtro nomeia a chave de partição com a qual a collection foi criada.

Diretório de partições

Consulta O(1): o valor da partição resolve para (offset, length) no segmento base. Sem geração de candidatos, sem ponto de entrada em grafo.

Varredura de fatia contígua

Pontuação exata SIMD sobre um bloco sequencial. O recall neste caminho é 1,0 — é uma varredura, não uma aproximação. Os valores medidos de p50/p95 para esta etapa são publicados na página de benchmarks, cada um vinculado ao seu gate de recall e rig.

União de delta

Linhas com a mesma chave no delta em formato Arrow são pontuadas pelo mesmo caminho. Uma escrita fica visível para a próxima consulta imediatamente.

Visibilidade MVCC

Hits filtrados pelo LSN do snapshot: versões tombstoned e supersedidas nunca emergem. Top-k retorna com o payload do explain anexado.

Partições superdimensionadas seguem um fork declarado: build_ivf posiciona um IVF por partição sobre qualquer partição acima do limiar de linhas, e as consultas são roteadas por ele com um rerank exato — calibrado contra um piso de recall e nomeado no plano.

03 O fork do explain

Todo resultado nomeia seu plano.

explain=True retorna o plano físico que a consulta efetivamente executou. Na chave de partição, você obtém o scan de fatia contígua. Partições superdimensionadas declaram o fork IVF. Filtros fora da chave recaem em scatter-gather — e o payload explica o motivo.

explain
hits = col.search(qvec, where={"tenant_id": "acme"}, top_k=10, explain=True)

hits["explain"]["plan"]
# on the partition key  → "PartitionSliceExactF32"   # one contiguous slice, exact, recall 1.0
# oversized partition   → "PartitionIVFRerankF32"   # per-partition IVF + exact rerank
# off-key filter        → "ScatterGatherExact"      # fallback — and it says why:

hits["explain"]["fallback_reason"]
# "path is not the physical partition key"
04 Escritas e tempo

Nada é sobrescrito. Versões são supersedidas.

O modelo de escrita é MVCC append-only. upsert grava uma nova versão de um id lógico e marca a anterior como supersedida; delete posiciona um tombstone em um LSN de exclusão; snapshot() fixa uma visão de leitura consistente; compact() incorpora o delta à base e descarta o que nenhum snapshot pode ver.

python
col.upsert(vectors, ids=ids, metadata=metadata)   # a new version; the prior one is superseded
col.delete(["doc-41"])                            # tombstone at a delete LSN — no in-place erase
lsn = col.snapshot()                              # pin a consistent read view at an LSN
col.compact()                                     # fold delta into base; drop superseded rows
col.build_ivf(min_rows=20000, target_recall=0.98)
ChamadaO que faz
adicionar / add_textsInsere novas linhas. Ids duplicados são rejeitados — uma segunda linha física para um id lógico exige upsert, por design.
inserção / upsert_textsGrava uma nova versão de um id lógico; a versão anterior é supersedida, nunca sobrescrita no lugar.
buscar / search_textTop-k filtrado. explain=True anexa o plano físico ao resultado.
deleteAplica tombstone em linhas lógicas em um LSN de exclusão.
compactIncorpora o delta ao segmento base; descarta versões tombstoned e supersedidas.
build_ivfConstrói IVF por partição sobre partições acima do limiar de linhas, calibrado a um piso de recall.
snapshotRetorna um LSN que fixa uma visão de leitura consistente.
save / statsPersiste a coleção em disco; reporta contagens de linhas, partições e informações de layout.
Painel 02 · Direção — a spec de arquitetura

Tudo abaixo é especificação, não referência de API publicada. É o substrato para o qual o runtime está convergindo. A interface voltada ao SDK está congelada, de modo que a troca subjacente é invisível para os chamadores.

05 O substrato-alvo

Um planner. Um IR plano. Um executor.

Três front ends convergem para um único planner, que emite uma representação intermediária física plana, executada por um executor vetorizado Mojo diretamente sobre buffers Arrow.

Front ends

O modelo de memória (remember · recall · as_of), a API de consulta (point_get · scan · search · hybrid_search) e o fabric. Um contrato de entrada único; nenhum engine por API.

Um planner

Planejamento lógico e físico em um único lugar. A seletividade é estimada a partir de estatísticas de segmento; o plano é explícito e retornado com o resultado.

Um IR plano

Um array plano de operadores vinculados por slots inteiros. O registrador entre operadores é um row set — um bitmap, row-ids ordenados ou um vetor de seleção.

Um executor Mojo

Execução vetorizada sobre buffers Arrow e arrays de candidatos FAISS. O hot path SIMD permanece fora do Python; páginas Parquet comprimidas são decodificadas em scratch buffers primeiro.

Arrow delta + WAL

A camada de mutação

Um write-ahead log para durabilidade e ordenação, e um delta mutável em formato Arrow para visibilidade imediata — a camada de tabela que o Parquet não oferece por conta própria.

Segmentos Parquet

Selados, imutáveis

Segmentos colunares comprimidos e duráveis. Estatísticas de rodapé orientam a poda de segmentos e row-groups; arquivos selados nunca são mutados.

sidecars .vidx

FAISS ANN

Índices FAISS por segmento, vinculados ao checksum e à versão do segmento, mapeados como somente leitura com tempo de vida atrelado ao snapshot de leitura.

Sidecars escalares + esparsos

Poda e léxico

Zone maps, bloom filters e bitmaps para poda; um sidecar BM25 para recuperação esparsa e fusão de scores.

flat IR — conjunto de operadores
SCAN  FILTER  PROJECT  POINT_GET  RANGE_GET  AGGREGATE  TOP_K
HASH_JOIN  HASH_GROUP_BY  SORT
ANN_SEARCH  SPARSE_SEARCH  FUSE  RERANK  MATERIALIZE
06 O caminho de escrita

WAL primeiro. Visível imediatamente. Selado em segundo plano.

WAL append

Frames append-only com checksums e LSNs monotônicos. A recuperação repete registros após o último LSN selado e trunca no primeiro checksum inválido.

Arrow delta

A escrita chega ao delta mutável e fica consultável imediatamente — segmentos selados e delta se unem por um único caminho de scan.

Selagem em segundo plano

Ultrapassado um limite de tamanho, linhas ou idade, o delta é ordenado e gravado como um segmento Parquet com seu .vidx e sidecars, depois publicado por uma troca atômica de manifesto.

Compactação

Mesclagens em segundo plano unem segmentos pequenos, descartam linhas com tombstone e reconstroem os sidecars — com orçamento controlado, para que implantações on-device permaneçam silenciosas.

Segmentos selados nunca são mutados. Uma leitura fixa (snapshot de manifesto, LSN); escritores selam novos segmentos e trocam o manifesto sem perturbar leitores em andamento. A coleta de lixo aguarda o snapshot ativo mais antigo.

07 ANN filtrado como planejamento

O filtro escolhe o plano, não o contrário.

ANN filtrado é planejamento adaptativo por seletividade: o planejador estima quantas linhas sobrevivem ao filtro a partir das estatísticas de segmento e então escolhe a estratégia mais barata que mantém o contrato de recall.

Seletivo

Prefilter → exato

Prefilter escalar ou bitmap primeiro, depois pontuação SIMD exata sobre os sobreviventes. Abaixo de um limite de linhas, o ANN é ignorado por completo — varredura exata, recall 1.0.

Moderado

Travessia com allow-bitmap

A travessia ANN carrega um allow-bitmap, de modo que o índice só expõe linhas admitidas pelo filtro.

Amplo

ANN → pós-filtro

ANN primeiro com over-fetch adaptativo, depois post-filter. O filtro remove pouco, então a geração de candidatos lidera.

08 Status

Verificações de correção precedem qualquer número de desempenho.

O runtime entregue é verificado por suítes de paridade executadas contra ambas as implementações do motor, e toda consulta pode nomear o plano físico que utilizou. Esta é a ordem de operações aqui: verificações de correção primeiro, medição depois.

Benchmarks são publicados sob um contrato de imparcialidade — recall equivalente, hardware equivalente, resultados separados por transporte, vitória / empate / derrota reportados. Os primeiros resultados medidos estão agora disponíveis na página de benchmarks, cada número acompanhado de suas condições completas: hardware, conjunto de dados, dimensão, seletividade, recall e transporte. Todo multiplicador permanece uma hipótese fora das condições declaradas ao seu lado.

Leia a metodologia de benchmarkVer a superfície do produto