Plugin AI Search
Plugin AI Search
Ce plugin est actuellement en bêta. Les API peuvent changer d'une version mineure à l'autre. Importez depuis @databricks/appkit/beta. Consultez Niveaux de stabilité des plugins.
Interrogez des index Databricks Vector Search avec recherche hybride, reranking et pagination par curseur depuis votre application AppKit.
Fonctionnalités clés :
- Alias nommés pour plusieurs index Vector Search
- Modes de query hybride, ANN et texte intégral
- Reranking facultatif avec contrôle au niveau des colonnes
- Pagination par curseur pour les grands ensembles de résultats
- Authentification par service principal (par défaut) et on-behalf-of-user
- Index d'embeddings autogérés via une fonction
embeddingFnpersonnalisée
Utilisation de base
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,
},
},
}),
],
});Options de configuration
| Option | Type | Valeur par défaut | Description |
|---|---|---|---|
indexes | Record<string, IndexConfig> | — | Obligatoire. Correspondance entre les noms d'alias et les configurations d'index |
timeout | number | 30000 | Délai d'expiration des requêtes, en ms |
Alias d'index
Les alias d'index vous permettent de référencer plusieurs index Vector Search par leur nom. L'alias est utilisé dans les routes d'API et les appels programmatiques :
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",
},
},
});Un alias sans indexName propre utilise par défaut la variable
d'environnement DATABRICKS_VS_INDEX_NAME. Si plusieurs alias omettent
indexName, ils pointent tous vers ce même index physique (tout en conservant
leurs propres columns, queryType, etc.). Attribuez un indexName explicite à
chaque alias lorsque vous souhaitez cibler des index distincts.
IndexConfig
| Champ | Type | Valeur par défaut | Description |
|---|---|---|---|
indexName | string | DATABRICKS_VS_INDEX_NAME | Nom Unity Catalog à trois niveaux (catalog.schema.index). Utilise par défaut la variable d'environnement DATABRICKS_VS_INDEX_NAME s'il est omis. |
columns | string[] | découvertes automatiquement en développement | Colonnes à renvoyer dans les résultats de query. Facultatif en développement : si elles sont omises, le plugin les lit dans la table source de l'index et émet un avertissement. À définir explicitement en production, où une valeur manquante n'est pas renseignée automatiquement. |
queryType | "ann" | "hybrid" | "full_text" | "hybrid" | Mode de recherche |
numResults | number | 20 | Nombre maximal de résultats par query |
reranker | boolean | { columnsToRerank: string[] } | — | Active le reranking. Indiquez true pour reclasser toutes les colonnes de résultats, ou précisez un sous-ensemble |
auth | "service-principal" | "on-behalf-of-user" | "service-principal" | Mode d'authentification pour l'exécution des query |
pagination | boolean | — | Active la pagination par curseur |
endpointName | string | — | Nom de l'endpoint Vector Search. Requis lorsque pagination vaut true |
embeddingFn | (text: string) => Promise<number[]> | — | Fonction d'embedding personnalisée pour les index d'embeddings auto-gérés |
Types de requêtes
hybrid— Combine la similarité vectorielle et la recherche par mots-clés. Idéale pour une recherche polyvalente.ann— Recherche approximative des plus proches voisins, basée uniquement sur les embeddings. Idéale pour la similarité sémantique.full_text— Recherche par mots-clés, sans embedding requis.
Reranking
Le reranking améliore la pertinence des résultats en appliquant un modèle de seconde passe aux candidats initiaux :
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description", "category"],
reranker: { columnsToRerank: ["name", "description"] },
},
},
});Passez reranker: true pour effectuer un reclassement sur l'ensemble des colonnes renvoyées.
Authentification on-behalf-of-user
Par défaut, les queries s'exécutent sous l'identité du service principal de l'application. Définissez auth: "on-behalf-of-user" pour les exécuter sous l'identité de l'utilisateur connecté :
aiSearch({
indexes: {
documents: {
indexName: "catalog.schema.documents_idx",
columns: ["id", "title", "body"],
auth: "on-behalf-of-user",
},
},
});Pagination
Activez la pagination par curseur pour parcourir de grands ensembles de résultats :
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description"],
pagination: true,
endpointName: "my-vector-search-endpoint",
},
},
});endpointName est requis lorsque pagination vaut true. Utilisez la route /:alias/next-page pour récupérer les pages suivantes.
Index à embeddings autogérés
Pour les index qui gèrent leurs propres embeddings, fournissez une fonction embeddingFn qui prend une chaîne de requête en entrée et renvoie un vecteur :
import { embed } from "./my-embedding-client";
aiSearch({
indexes: {
products: {
indexName: "catalog.schema.products_idx",
columns: ["id", "name", "description"],
queryType: "ann",
embeddingFn: (text) => embed(text),
},
},
});Routes HTTP
Les routes sont montées sur /api/ai-search.
| Méthode | Chemin | Description |
|---|---|---|
POST | /:alias/query | Interroger un index par son alias |
POST | /:alias/next-page | Récupérer la page de résultats suivante (nécessite pagination: true) |
GET | /:alias/config | Renvoyer la configuration résolue pour un alias d'index |
Interroger un index
POST /api/ai-search/:alias/query
Content-Type: application/json
{
"queryText": "machine learning guide",
"numResults": 10
}Réponse :
{
"results": [
{
"score": 0.87,
"data": { "id": "42", "name": "Intro to ML", "description": "..." }
}
],
"totalCount": 1,
"queryTimeMs": 35,
"queryType": "hybrid",
"nextPageToken": "eyJvZmZzZXQiOjEwfQ=="
}Chaque résultat comporte son score de pertinence ainsi que les colonnes renvoyées sous data. nextPageToken vaut null, sauf si pagination est activé et que d'autres résultats sont disponibles.
Récupérer la page suivante
POST /api/ai-search/:alias/next-page
Content-Type: application/json
{
"queryText": "machine learning guide",
"pageToken": "eyJvZmZzZXQiOjEwfQ=="
}Obtenir la configuration de l'index
GET /api/ai-search/:alias/configRenvoie la configuration IndexConfig résolue pour l'alias (hors embeddingFn).
Accès programmatique
Le plugin expose une méthode query destinée à un usage côté serveur :
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);Passez des valeurs de remplacement facultatives en deuxième argument de query pour ajuster numResults ou d'autres paramètres spécifiques à l'appel.
Mise en cache
Les résultats des requêtes sont mis en cache avec un TTL court (60 s) : ainsi, des requêtes identiques répétées — y compris lorsqu'un composant effectue un nouveau rendu ou est monté deux fois — réutilisent un seul appel à Vector Search au lieu d'interroger l'index à chaque fois. La route de page suivante, elle, n'est pas mise en cache : un jeton de page est un curseur à usage unique qui identifie déjà la page exacte.
La clé de cache couvre tout ce qui influe sur les résultats : l'index résolu, queryText, queryVector (haché), queryType, numResults, les columns résolues, les filters et l'activation ou non du reranking. Deux requêtes qui diffèrent sur l'un de ces éléments sont mises en cache séparément.
Isolation par utilisateur
Pour les index auth: "on-behalf-of-user", l'identité de l'appelant fait partie de la clé de cache : un utilisateur ne voit donc jamais les résultats mis en cache d'un autre utilisateur, et une query on-behalf-of-user ne lit jamais une entrée alimentée par un service principal. Les index en service principal, eux, partagent une seule et même entrée de cache entre tous les appelants.
Hook React
useAiSearchQuery lit les index configurés dans la configuration client du plugin et envoie une requête POST vers la route /:alias/query appropriée : l'interface n'a donc jamais besoin de coder un alias en dur. Lorsqu'un seul index est configuré, aucun argument n'est requis ; passez { alias } pour cibler un index précis.
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 accepte également un objet de requête complet ({ queryText, numResults, filters, ... }) pour un contrôle appel par appel. Le champ indexes du hook répertorie tous les index configurés, ce qui vous permet de construire un sélecteur d'index.