La bibliothèque Go pour rendre votre documentation interrogeable
Vos fichiers sont indexés. Vos questions trouvent des réponses. Pas de SaaS, pas de boîte noire.
Le problème
Vous avez de la documentation, du code source, des images, des PDF. Vos utilisateurs, ou vos agents IA, posent des questions, et personne ne sait où chercher. La recherche plein-texte classique ne comprend pas le sens des requêtes. Les outils vectoriels du marché sont des services fermés, facturés à l’usage, dont vous ne contrôlez rien. Vous voulez un index local, rapide et interopérable avec vos outils.
La solution
Amoxtli est une bibliothèque Go pour ingérer des fichiers et y faire de la recherche documentaire. C’est aussi un outil en ligne de commande prêt à l’emploi, pour commencer sans écrire une ligne de Go.
Amoxtli veut dire « livre, codex » en nahuatl.
Ce que fait Amoxtli
Un seul index, ou plusieurs fusionnés
Deux façons de déployer, selon votre contexte :
Index local, embarqué dans l’application. Bleve pour le plein-texte (BM25), sqlite-vec pour la recherche vectorielle par embeddings. Aucun serveur à installer : les index vivent dans des fichiers, au même endroit que votre base de documents. C’est le bon choix pour un outil CLI, une application mono-instance, ou un index qui doit suivre le projet (par défaut, tout tient dans le répertoire .amoxtli/ de l’espace de travail).
PostgreSQL, pour mutualiser. Le backend index/postgres combine la recherche plein-texte de PostgreSQL et pgvector pour les embeddings, dans une seule base. C’est le bon choix quand plusieurs applications ou instances partagent le même corpus, ou quand vous avez déjà un PostgreSQL en production.
| Local (Bleve + sqlite-vec) | PostgreSQL (FTS + pgvector) | |
|---|---|---|
| Installation | Aucune, fichiers sur disque | Serveur PostgreSQL + extension pgvector |
| Plein-texte | BM25 via Bleve | FTS natif |
| Vectoriel | sqlite-vec | pgvector |
| Cas d’usage | CLI, application embarquée, index par projet | Plusieurs clients, corpus partagé, infra existante |
Dans les deux cas, vous pouvez combiner plusieurs index : leurs résultats sont fusionnés par Reciprocal Rank Fusion pondérée, chaque backend contribuant avec son poids. Faire cohabiter un index lexical et un index vectoriel, c’est précisément le montage sur lequel reposent les mécanismes sémantiques (HyDE, reranking). Et si aucun des backends fournis ne vous convient, tout type qui implémente index.Index peut servir d’indexeur.
Ingestion universelle
Un seul pipeline fait tout converger vers du markdown indexable :
- Markdown natif : parsé directement, découpé en sections.
- Code source : indexé déclaration par déclaration via tree-sitter (Go, JavaScript, TypeScript, Python, PHP), sans binaire externe.
- Fichiers bureautiques : conversion via pandoc ou LibreOffice (
.docx,.odt,.rtf,.epub,.html…). - PDF : extraction par LLM (Mistral, Marker, ou tout endpoint compatible).
- Images : décrites par un LLM vision, stockées par hash de contenu, réaffichables via MCP. Les images trop grandes sont ré-encodées avant l’appel au modèle, au lieu de faire échouer l’indexation.
Recherche sémantique, pas seulement lexicale
Avec un client LLM configuré, vous pouvez activer :
- HyDE (Hypothetical Document Embeddings) : la requête est transformée en document hypothétique avant l’embedding, ce qui améliore le rappel sémantique.
- Grounding : un LLM juge si les résultats soutiennent une réponse fiable, avec un verdict (
valid,partial,invalid) et un score. - Recherche itérative : si le grounding juge les résultats insuffisants, la requête est reformulée et relancée.
- Reranking LLM : les candidats sont réordonnés par pertinence.
Ces mécanismes sont désactivés par défaut. Sans client LLM, la recherche reste purement lexicale ou vectorielle. Dès que vous en configurez un, HyDE mérite d’être essayé sur un index vectoriel ; activez le reranking ou le grounding quand la précision des passages transmis compte.
Tout cela se mesure : le package eval fournit Recall@k, MRR et nDCG@k, avec des benchmarks sur des jeux de questions-réponses réels (SciFact, jeux SQuAD-like multilingues).
Indexation de code source
Tree-sitter embarqué, sans dépendance système. Chaque fonction, méthode, type et commentaire de documentation devient une section indexée, avec ses métadonnées. La recherche croisée entre doc et code est native :
amoxtli add $(git ls-files '*.go')
amoxtli search "gestion d'erreur" --filter extension=go
amoxtli search "gestion d'erreur" --filter extension=md # doc seule
Images décrites, stockées, réaffichées
Les images sont décrites par un LLM vision, stockées par hash de contenu, et servies via des URI amoxtli://images/<hash> qui survivent au rendu. Le serveur MCP expose l’outil fetch_image pour qu’un agent puisse les montrer à l’utilisateur.
Un outil CLI complet
Pas besoin d’écrire du Go pour commencer :
amoxtli init
amoxtli add ./docs/*.md
amoxtli add $(git ls-files '*.go') -c code
amoxtli search "modèle de concurrence"
amoxtli search --deep "comment fonctionne le grounding ?"
Un espace de travail par projet (.amoxtli/), une configuration YAML avec interpolation de variables d’environnement, un .amoxtlignore qui fonctionne comme un .gitignore, des filtres sur les métadonnées (filename, extension, size, mtime, dirname, indexed_at, lang), une pagination par curseur.
Serveur MCP pour vos agents
Amoxtli sert un serveur MCP (Model Context Protocol) sur stdio ou HTTP, et expose les outils search, fetch_sections, list_collections et list_documents. Vos agents IA interrogent votre base documentaire en temps réel, avec accès aux métadonnées et aux images.
En pratique
# Installation
go install github.com/bornholm/amoxtli/cmd/amoxtli@latest
# Ou, depuis le dépôt
make build
# Initialiser un espace de travail
amoxtli init
# Indexer de la documentation et du code
amoxtli add ./docs/*.md
amoxtli add $(git ls-files '*.go') -c code
# Rechercher
amoxtli search "authentification"
amoxtli search "authentification" --filter extension=md
amoxtli search --deep "comment gérer les erreurs ?"
En tant que bibliothèque Go :
store, _ := gorm.NewSQLiteStore("/data/kb/data.sqlite")
bleveIdx, _ := bleve.OpenOrCreate(ctx, "/data/kb/index.bleve")
codex, _ := amoxtli.New(ctx,
amoxtli.WithStore(store),
amoxtli.WithIndexers(amoxtli.Indexer{ID: "bleve", Index: bleveIdx, Weight: 1.0}),
)
collID, _ := codex.CreateCollection(ctx, "docs")
codex.IndexFile(ctx, collID, "guide.md", file)
results, _ := codex.Search(ctx, "comment faire…")
Pour qui ?
- Les développeurs qui veulent un moteur de recherche documentaire intégrable en quelques lignes de Go.
- Les équipes qui veulent rendre leur documentation interrogeable par des agents IA.
- Les projets open source qui veulent offrir une recherche avancée sur leur code et leur doc.
- Toute organisation qui a besoin d’un index local, sans dépendance à un service tiers.
Code source
Amoxtli est publié sous licence MIT. Tout le code est public, inspectable et modifiable.
Voir le dépôt sur GitHub. Contributions, issues et discussions bienvenues.
