Plugin AI Search
Plugin AI Search
Este plugin está atualmente em beta. As APIs podem mudar entre versões menores. Importe de @databricks/appkit/beta. Consulte Níveis de estabilidade de plugins.
Consulte índices do Databricks Vector Search com busca híbrida, reranking e paginação por cursor a partir do seu app AppKit.
Principais recursos:
- Aliases de índice nomeados para múltiplos índices do Vector Search
- Modos de consulta híbrido, ANN e de texto completo
- Reranking opcional com controle em nível de coluna
- Paginação baseada em cursor para grandes conjuntos de resultados
- Autenticação via service principal (padrão) e on-behalf-of-user
- Índices de embedding autogerenciados por meio de uma
embeddingFnpersonalizada
Uso básico
import { createApp, server } from "@databricks/appkit";
import { aiSearch } from "@databricks/appkit/beta";
await createApp({
plugins: [
server(),
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description"],
queryType: "hybrid",
numResults: 20,
},
},
}),
],
});Opções de configuração
| Opção | Tipo | Padrão | Descrição |
|---|---|---|---|
indexes | Record<string, IndexConfig> | — | Obrigatório. Mapeamento de aliases para configurações de índice |
timeout | number | 30000 | Tempo limite da consulta, em ms |
Aliases de índice
Os aliases de índice permitem referenciar vários índices do Vector Search pelo nome. O alias é usado em rotas de API e em chamadas programáticas:
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description"],
},
docs: {
indexName: "catalog.schema.docs_idx",
columns: ["id", "title", "content", "url"],
queryType: "full_text",
},
},
});Um alias sem indexName próprio recorre à variável de ambiente
DATABRICKS_VS_INDEX_NAME. Se vários aliases omitirem indexName, todos
apontarão para esse mesmo índice físico (cada um com suas próprias columns,
queryType, etc.). Defina um indexName explícito em cada alias
quando quiser índices distintos.
IndexConfig
| Campo | Tipo | Padrão | Descrição |
|---|---|---|---|
indexName | string | DATABRICKS_VS_INDEX_NAME | Nome de três níveis do Unity Catalog (catalog.schema.index). Quando omitido, usa a variável de ambiente DATABRICKS_VS_INDEX_NAME. |
columns | string[] | descoberto automaticamente em desenvolvimento | Colunas a retornar nos resultados da consulta. Opcional em desenvolvimento — quando omitido, o plugin as lê da tabela de origem do índice e emite um aviso. Defina explicitamente em produção, onde um valor ausente não é preenchido automaticamente. |
queryType | "ann" | "hybrid" | "full_text" | "hybrid" | Modo de busca |
numResults | number | 20 | Número máximo de resultados por consulta |
reranker | boolean | { columnsToRerank: string[] } | — | Ativa o reranking. Passe true para fazer reranking em todas as colunas do resultado ou especifique um subconjunto |
auth | "service-principal" | "on-behalf-of-user" | "service-principal" | Modo de autenticação para a execução da consulta |
pagination | boolean | — | Ativa a paginação baseada em cursor |
endpointName | string | — | Nome do endpoint de Vector Search. Obrigatório quando pagination for true |
embeddingFn | (text: string) => Promise<number[]> | — | Função de embedding personalizada para índices de embedding autogerenciados |
Tipos de consulta
hybrid— Combina similaridade vetorial e busca por palavras-chave. Ideal para recuperação de uso geral.ann— Busca por vizinhos mais próximos aproximados usando apenas embeddings. Ideal para similaridade semântica.full_text— Busca baseada em palavras-chave, sem necessidade de embeddings.
Reranking
O reranking melhora a relevância dos resultados executando um modelo de segundo estágio sobre os candidatos iniciais:
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description", "category"],
reranker: { columnsToRerank: ["name", "description"] },
},
},
});Passe reranker: true para reordenar os resultados considerando todas as colunas retornadas.
Autenticação on-behalf-of-user
Por padrão, as queries são executadas com o service principal do app. Defina auth: "on-behalf-of-user" para executá-las com a identidade do usuário autenticado:
aiSearch({
indexes: {
documents: {
indexName: "catalog.schema.documents_idx",
columns: ["id", "title", "body"],
auth: "on-behalf-of-user",
},
},
});Paginação
Habilite a paginação por cursor para percorrer grandes conjuntos de resultados:
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description"],
pagination: true,
endpointName: "my-vector-search-endpoint",
},
},
});endpointName é obrigatório quando pagination é true. Use a rota /:alias/next-page para buscar as páginas seguintes.
Índices com embeddings autogerenciados
Para índices que gerenciam seus próprios embeddings, forneça uma embeddingFn que receba uma string de consulta e retorne um vetor:
import { embed } from "./my-embedding-client";
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description"],
queryType: "ann",
embeddingFn: (text) => embed(text),
},
},
});Rotas HTTP
As rotas são montadas em /api/ai-search.
| Método | Caminho | Descrição |
|---|---|---|
POST | /:alias/query | Consulta um índice pelo alias |
POST | /:alias/next-page | Obtém a próxima página de resultados (requer pagination: true) |
GET | /:alias/config | Retorna a configuração resolvida para um alias de índice |
Consultar um índice
POST /api/ai-search/:alias/query
Content-Type: application/json
{
"queryText": "machine learning guide",
"numResults": 10
}Resposta:
{
"results": [
{
"score": 0.87,
"data": { "id": "42", "name": "Intro to ML", "description": "..." }
}
],
"totalCount": 1,
"queryTimeMs": 35,
"queryType": "hybrid",
"nextPageToken": "eyJvZmZzZXQiOjEwfQ=="
}Cada resultado traz seu score de relevância e as colunas retornadas em data. nextPageToken é null, a menos que pagination esteja habilitado e haja mais resultados disponíveis.
Buscar a próxima página
POST /api/ai-search/:alias/next-page
Content-Type: application/json
{
"queryText": "machine learning guide",
"pageToken": "eyJvZmZzZXQiOjEwfQ=="
}Obter configuração do índice
GET /api/ai-search/:alias/configRetorna o IndexConfig resolvido para o alias (excluindo embeddingFn).
Acesso programático
O plugin expõe um método query para uso no lado do servidor:
import { createApp, server } from "@databricks/appkit";
import { aiSearch } from "@databricks/appkit/beta";
const AppKit = await createApp({
plugins: [
server(),
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description"],
},
},
}),
],
});
const result = await AppKit.aiSearch.query("products", {
queryText: "machine learning guide",
});
console.log(result.results);Passe substituições opcionais como segundo argumento de query para ajustar numResults ou outras configurações por chamada.
Cache
Os resultados das queries são armazenados em cache com um TTL curto (60s), de modo que queries idênticas repetidas — inclusive quando um componente re-renderiza ou é montado duas vezes — reutilizem uma única chamada ao Vector Search em vez de acessar o índice todas as vezes. A rota de próxima página não é armazenada em cache: um token de página é um cursor de uso único e já identifica exatamente a página desejada.
A chave de cache cobre tudo o que altera os resultados: o índice resolvido, queryText, queryVector (com hash), queryType, numResults, as columns resolvidas, os filters e se o reranking está ativado. Duas queries que diferem em qualquer um desses itens são armazenadas em cache separadamente.
Isolamento por usuário
Em índices com auth: "on-behalf-of-user", a identidade de quem faz a chamada compõe a chave de cache, de modo que um usuário nunca vê os resultados em cache de outro — e uma consulta on-behalf-of-user nunca lê uma entrada preenchida por um service principal. Já os índices de service principal compartilham uma única entrada de cache entre todos os chamadores.
Hook React
useAiSearchQuery lê os índices configurados na config de cliente do plugin e faz POST para a rota /:alias/query correta, de modo que a interface nunca precisa fixar um alias no código. Com apenas um índice configurado, ele não exige argumentos; passe { alias } para direcionar a consulta a um índice específico.
import { useAiSearchQuery } from "@databricks/appkit-ui/react/beta";
function Search() {
const { search, data, loading, error } = useAiSearchQuery();
return (
<>
<input onKeyDown={(e) => e.key === "Enter" && search(e.currentTarget.value)} />
{error && <p>{error}</p>}
{data?.results.map((r, i) => (
<div key={i}>{JSON.stringify(r.data)}</div>
))}
</>
);
}search também aceita um objeto de requisição completo ({ queryText, numResults, filters, ... }) para controle por chamada. O campo indexes do hook lista todos os índices configurados, que você pode usar para criar um seletor de índices.