Capability Embedding¶
embedding transforme des textes en vecteurs numériques derrière un port
outbound provider-neutral. Le port calcule seulement les vecteurs : il ne
stocke ni document, ni chunk, ni conversation.
Choisir La Bonne Primitive¶
| Besoin | Primitive Arclith | Responsabilité |
|---|---|---|
| produire une réponse ou une structure | llm |
complétion et raisonnement |
| transformer du texte en vecteur | embedding |
calcul numérique sans persistance |
| rechercher les vecteurs voisins | vector-store |
indexation et recherche vectorielle |
| conserver l'entité et ses métadonnées | repository |
source de vérité métier |
| conserver le contenu binaire | storage |
fichiers et blobs |
Un pipeline RAG assemble donc explicitement les responsabilités :
| Text Only | |
|---|---|
L'index vectoriel reste reconstruisible. Le service consommateur doit conserver avec chaque entrée au moins le modèle, la dimension, le hash du contenu et la stratégie de chunking afin de pouvoir détecter puis réindexer un contenu obsolète.
Contrat Commun¶
EmbeddingResponse garantit :
- au moins un résultat ;
- des indices continus
0..n-1, dans l'ordre des entrées ; - un seul
model_nameet une seule dimension pour tout le batch ; - un vecteur non vide dont la longueur égale
dimensions; - des métriques de tokens optionnelles via
EmbeddingUsage.
Les entrées vides ou composées uniquement d'espaces sont rejetées avant tout
appel provider. Les adapters concrets traduisent leurs erreurs en
EmbeddingUnavailable, EmbeddingAuthenticationError,
EmbeddingRateLimitError, EmbeddingInvalidInput ou
EmbeddingDimensionMismatch. Les messages ne doivent jamais inclure de secret
ou d'URL contenant des credentials.
Adapter Deterministic¶
deterministic ne requiert aucune dépendance externe. Pour un même
model_name, un même texte et une même dimension, il produit le même vecteur
entre deux processus. Il sert aux tests, aux POC et aux smokes locaux ; il ne
modélise aucune proximité sémantique réelle et ne doit pas être utilisé comme
moteur de recherche en production.
| Bash | |
|---|---|
La commande est idempotente et écrit
config/adapters/outbound/embedding.yaml :
| YAML | |
|---|---|
Le fichier scoped contient son propre sélecteur adapter. Il n'ajoute aucune
clé à config/adapters/adapters.yaml.
Adapter OpenAI-Compatible¶
openai-compatible appelle POST /embeddings sur un endpoint qui expose le
protocole OpenAI Embeddings. Il convient notamment à LM Studio, vLLM, LocalAI
ou à un mode compatible d'Ollama, à condition que le runtime et le modèle
choisis fournissent réellement cet endpoint.
Installer l'extra HTTP et générer la configuration :
| Bash | |
|---|---|
Le nom nomic-embed-text n'est qu'un exemple. Copier l'identifiant exact
affiché par le runtime local : Arclith ne choisit, ne télécharge et ne charge
aucun modèle à la place de l'utilisateur.
| YAML | |
|---|---|
base_url doit contenir le préfixe API, généralement /v1. Les URLs avec
credentials, query string ou fragment sont refusées afin que les erreurs ne
puissent pas exposer de secret. api_key: local-dev est une valeur locale non
secrète destinée aux runtimes qui exigent un header. Pour un endpoint protégé,
laisser la valeur hors Git et résoudre adapters.embedding.api_key avec la
capability secrets. Ne jamais passer une clé de production au
scaffold pour l'écrire dans le YAML.
Hôte Et Conteneur¶
- processus lancé sur l'hôte :
http://127.0.0.1:1234/v1; - conteneur Docker Desktop macOS/Windows vers l'hôte :
http://host.docker.internal:1234/v1; - Linux ou Kubernetes : utiliser une route explicitement configurée, un service
DNS ou un endpoint réseau autorisé ; ne pas supposer que
host.docker.internalexiste.
Tous les runtimes locaux OpenAI-compatible pour le chat n'exposent pas
forcément /v1/embeddings, et tous les modèles ne savent pas produire des
embeddings. Vérifier les deux capacités dans l'interface ou la documentation du
runtime avant le smoke.
Smoke Manuel Optionnel¶
Ce smoke vérifie le protocole sans faire partie des tests automatisés :
| Bash | |
|---|---|
Les tests Arclith utilisent un transport HTTP simulé. Ils ne nécessitent ni
réseau, ni LM Studio, ni Ollama. L'adapter découpe les sous-batches, réordonne
les résultats selon l'index provider, agrège l'usage, vérifie chaque dimension
et traduit auth, rate limit, timeout et indisponibilité vers les erreurs
communes. normalize vaut false quand le champ est omis. Avec
normalize: true, l'adapter applique une normalisation L2 locale ; avec
false, il conserve exactement les vecteurs du provider.
Adapter OpenAI Officiel¶
openai appelle l'API Embeddings officielle sur POST /v1/embeddings. Il
réutilise l'extra HTTP optionnel arclith[embedding] et n'ajoute pas le SDK
OpenAI à l'installation minimale.
La documentation OpenAI consultée lors de cette implémentation expose notamment
text-embedding-3-small et text-embedding-3-large. Le catalogue CLI ne choisit
cependant aucun modèle à la place du service : vérifier les modèles
d'embedding disponibles et
les droits du projet OpenAI, puis passer l'identifiant voulu explicitement.
| Bash | |
|---|---|
Cette forme laisse le modèle choisir sa dimension native. Pour aligner
explicitement une collection vectorielle déjà dimensionnée, ajouter par
exemple --param dimensions=1536; le YAML généré contiendra alors
dimensions: 1536 au lieu de null.
La configuration générée garde le secret hors Git :
| YAML | |
|---|---|
Définir OPENAI_API_KEY dans l'environnement du processus, un secret
Kubernetes ou Vault. Ne jamais écrire la valeur dans le YAML versionné ni la
passer dans une commande conservée par l'historique du shell. Une absence de
clé résolue provoque une EmbeddingAuthenticationError actionnable avant tout
appel réseau.
Conformément à la référence Create
embeddings,
l'adapter envoie input, model, encoding_format: float et dimensions
uniquement quand cette dernière est configurée. Il réordonne les résultats par
index et expose prompt_tokens/total_tokens quand l'API les retourne. Le
champ provider user n'est pas alimenté automatiquement : un service ne doit
pas transmettre d'identifiant utilisateur brut sans décision explicite de
confidentialité.
Quand dimensions vaut null, l'adapter conserve la dimension renvoyée par le
modèle et vérifie qu'elle reste cohérente sur tous les sous-batches. Quand elle
est renseignée, toute différence déclenche EmbeddingDimensionMismatch. La
collection vectorielle cible doit être créée avec exactement la même dimension.
Les réponses 401/403, 429, les timeouts et les erreurs provider sont traduits
vers les exceptions communes sans reprendre la clé, le texte source ou le
payload dans le message. Les tests automatisés utilisent exclusivement
httpx.MockTransport; aucun appel à OpenAI n'est effectué par la suite de
tests.
Assemblage¶
| Python | |
|---|---|
Une application peut fournir un EmbeddingRegistry à app.embedding() pour
enregistrer un backend propre au projet sans importer son SDK dans le domaine.
Dans ce cas, adapter accepte le nom non vide déclaré par l'application ; le
registry valide ce nom à l'assemblage et retourne une erreur claire s'il n'est
pas enregistré :
| Python | |
|---|---|
La configuration scoped associée contient alors adapter: project.
Dimension Et Normalisation¶
La dimension configurée doit être identique à celle de la collection du vector-store. Cette vérification doit avoir lieu à l'assemblage ou avant la première écriture ; tronquer ou compléter silencieusement un vecteur rendrait l'index incohérent.
Avec normalize: true, les adapters deterministic et openai-compatible
appliquent une normalisation L2 locale. Les providers peuvent déjà retourner
des vecteurs normalisés ou proposer leur propre option. Le service doit
documenter la métrique de distance choisie avec le vector-store et ne pas
supposer que tous les providers ont la même stratégie.
Conversations Et Vie Privée¶
L'historique de chat ne doit pas être vectorisé automatiquement. Une telle indexation dupliquerait des données potentiellement personnelles, changerait leur durée de rétention et créerait un nouvel usage de recherche. Elle exige un use case explicite, une politique de consentement/rétention, un filtrage des données sensibles et une procédure de suppression cohérente entre source et index.
Validation Locale¶
Le smoke doit vérifier la dimension et l'ordre des résultats. La stabilité
concerne uniquement deterministic ; la pertinence sémantique et la
disponibilité du modèle appartiennent au runtime provider.