Aller au contenu
Tous les articles

Swelv· Article 1 sur 2

Un RAG sans vecteurs : le modèle cherche lui-même ses livres

Chaque mois, cinq livres choisis pour chaque lecteur. Le modèle n'invente aucun titre : il interroge le catalogue avec des outils, et le code vérifie tout.

6 min de lectureRead in English

Chaque mois, Swelv compose pour chaque lecteur une sélection de cinq livres, à partir de ce qu'il lit, aime et abandonne. Chaque livre arrive avec une accroche et un « pourquoi » qui cite ses propres lectures.

9:41

Une sélection qui te ressemble

Sélection mensuelle de Léa octobre 2026

Alexandre DumasLe Comte de Monte-Cristo

Le Comte de Monte-Cristo

Alexandre Dumas

Classique · Aventure · Historique

Camille, Léo ont aimé

Parce que tu as adoré Les Trois Mousquetaires

Pourquoi pour toi

Tu as adoré Les Trois Mousquetaires : même souffle, même Dumas, et une vengeance patiente qui tient sur mille pages.

+ Ajouter à ma liste
  1. 1Un livre qui existeTrouvé dans le catalogue, jamais cité de mémoire.
  2. 2Un axeSur cinq : trois sûrs, un voisin, une découverte.
  3. 3Une accroche cadréeQuelques tournures imposées, toujours au tutoiement.
  4. 4Un pourquoi vérifiableIl cite un livre du profil, et un lien réel entre les deux.
L'écran « Une sélection qui te ressemble », reconstitué avec les couleurs et la mise en page de l'app, sur un profil d'exemple. Trois des cinq livres, un par axe.

RAG : récupérer, puis générer

Un modèle de langage écrit très bien, mais il ne connaît pas notre catalogue, et il peut citer avec aplomb un livre qui n'existe pas. Le RAG (Retrieval-Augmented Generation) corrige ça : avant de répondre, on va chercher les bonnes informations, et le modèle écrit à partir d'elles.

La version la plus connue passe par des embeddings : on transforme les textes en vecteurs, et on cherche ceux qui sont les plus proches de la question. C'est idéal pour retrouver un passage dans une documentation. Pour recommander un livre, beaucoup moins : les vraies contraintes sont exactes (la bonne langue, pas un livre déjà lu, pas deux fois le même auteur), et une proximité de vecteurs n'en garantit aucune.

Swelv fait donc l'inverse : le modèle reçoit des outils, et cherche lui-même dans le catalogue, comme on interroge une base de données. C'est ce qu'on appelle le function calling : le modèle ne répond pas directement, il demande à appeler une fonction, le serveur l'exécute, et lui rend le résultat.

RAG classiqueembeddings
La question
Transformée en vecteur
Les passages les plus proches
Le modèle répond
  • + idéal pour retrouver du texte libre
  • − aucune garantie sur une règle exacte
RAG avec outilsoutils
Le profil du lecteur
Le modèle interroge la base↻ en boucle
Le code vérifie chaque choix
Le modèle écrit
  • + filtres exacts, résultats vérifiables
  • − plus d'allers-retours, donc plus lent
Deux façons d'aller chercher l'information avant de générer. Quand les contraintes sont exactes (la langue, un livre déjà lu, un auteur déjà proposé), les outils l'emportent.

Le défi. Laisser au modèle ce qu'il fait bien (comprendre des goûts, formuler des hypothèses, écrire) et garder dans le code tout ce qui doit être exact. Un modèle peut oublier une consigne ; une clause SQL, jamais.

La boucle

Le modèle reçoit le profil du lecteur, puis enchaîne les recherches : il formule une hypothèse (« il aime les grandes aventures historiques »), cherche, croise les résultats, élimine. Quand il propose ses cinq livres, le code relit chacun, et le renvoie au travail si l'un ne passe pas.

Le profil
  • livres adorés, coups de cœur
  • livres abandonnés, et pourquoi
  • activité récente
  • langues lues

Jamais les notes privées.

La boucleIA
modèleun filtredes livrescatalogue

Il formule des hypothèses, cherche, croise des listes, élimine.

Les contrôlesSQL
  • le livre existe ?
  • déjà lu, déjà proposé ?
  • bonne langue ?
  • même auteur deux fois ?

✗ → le modèle est relancé

5 livres
3 sûrs1 voisin1 découverte
Le modèle cherche lui-même dans le catalogue, avec des outils que le serveur traduit en requêtes. Puis le code relit chaque choix, et renvoie le modèle au travail tant qu'un livre ne passe pas.

Chaque recherche est un petit filtre que le modèle écrit, et que le serveur traduit en SQL. Le serveur y ajoute toujours ce que le modèle n'a pas à gérer : les livres déjà lus, et les langues du lecteur.

Le modèle écrit
chercher({  genre: "aventure",  thèmes: ["vengeance", "trahison"],  garder_sous: "comme_dumas"})
Le serveur exécute
SELECT titre, auteur, id FROM catalogueWHERE genre = $1  AND résumé ~* $2  AND id NOT IN (:déjà_lus)  AND langue IN (:langues_du_lecteur)ORDER BY note DESC LIMIT 20
+ ajouté par le serveur, à chaque recherche

Le modèle reçoit → une poignée de livres, chacun avec un identifiant à recopier tel quel, et la liste gardée sous un nom pour la croiser ensuite.

Un appel d'outil, avec des noms d'exemple. Le modèle écrit un filtre court ; le serveur le traduit en SQL paramétré et y ajoute ce que le modèle n'a pas à gérer.

La langue, apprise à la dure

Les premiers incidents de la fonctionnalité ont tous eu la même cause : la langue. Chacun a fait passer une règle du prompt vers le code.

Trois portes

  1. 01À chaque rechercheFiltrée d'office sur les langues du lecteur.
  2. 02Dans la boucleUn choix hors langue est refusé, le modèle relancé.
  3. 03À la validationDernier filet : le livre est retiré, puis remplacé.
Un quota par sélection, calculé sur les lectures récentes : la langue principale garde au moins trois places sur cinq.

Ce qui l'a appris

  1. 1Une lectrice francophone reçoit des livres dans d'autres langues.→ La langue n'était qu'un conseil dans le prompt : elle devient un filtre, à trois niveaux.
  2. 2L'accroche dans une langue, l'explication dans une autre.→ La langue de sortie est décidée par le code, et imposée au modèle.
  3. 3Des éditions mal étiquetées par la source des données.→ Un quota de langues par sélection, et la langue vérifiée par recoupement.
Chaque incident a déplacé une règle du prompt vers le code : un modèle peut oublier une consigne, pas une clause WHERE.

Le bon modèle n'est pas le moins cher

Avant de changer de modèle, on rejoue de vraies sélections sur les mêmes profils, et on compare : le coût, la durée, le nombre de corrections, et surtout la qualité des textes.

Coût par sélection, relatif

Le modèle d'avant× 1la référence
Le nouveau modèlechoisi÷ 3plus rapide, et les textes les plus riches : il nomme l'intrigue, cite les prix
Le moins cher÷ 30aucune correction nécessaire, mais des « pourquoi » plus courts et plus génériques

Le prompt système est le même pour tous les lecteurs : le fournisseur le sert presque entièrement depuis son cache.

Rejeu de vraies sélections sur les mêmes profils, avant de changer de modèle. Le moins cher n'a pas gagné : ce sont ses textes que le lecteur lit.

Ce que j'en retiens

  • Donner des outils plutôt que des souvenirs. Le modèle ne propose que ce qu'il a trouvé.
  • Ce qui compte va dans le code. Une consigne de prompt finit toujours par être oubliée.
  • Choisir le modèle sur ce que lit l'utilisateur, pas seulement sur la facture.