Sur Où est le marché ?, n'importe qui peut ajouter un marché : son nom, la ville, les jours et les horaires. C'est le principe du site, et ça marche plutôt bien. Mais il y a un revers : avant de publier un marché, il faut vérifier les informations. Un marché affiché le dimanche alors qu'il a lieu le mardi, c'est un visiteur qui se lève tôt pour rien. Et un site en qui on n'a plus confiance.
Au début, je vérifiais à la main. Chercher le site de la mairie, trouver la bonne page, lire les horaires, comparer avec la saisie... Comptez 5 bonnes minutes par marché quand tout va bien. Avec des centaines de marchés en attente, le calcul était vite fait : il me fallait une solution, rapidement, et surtout pas chère. C'est un projet perso : pas question de payer une API à chaque requête.
Ma solution : une petite application console .NET qui fait le travail à ma place, avec deux outils open source qui tournent entièrement sur mon PC portable : SearXNG pour chercher sur le web, et Ollama pour faire tourner l'IA.
TL;DR
- SearXNG (moteur de recherche auto-hébergé) trouve les pages qui parlent du marché, Ollama (IA locale) en extrait les jours et horaires.
- Tout tourne en local, dans Docker et sur la carte graphique d'un PC portable : 0 € d'API, aucune donnée envoyée à un service tiers.
- L'IA doit citer mot pour mot la phrase où elle a trouvé les horaires, et du code classique vérifie que cette phrase existe bien dans la page. Sinon, rien n'est publié.
- Un marché n'est publié automatiquement que si la source est fiable. Tout le reste part dans un fichier Excel pour une vérification manuelle, devenue très rapide.
Pourquoi pas ChatGPT ?
C'est la première question qu'on m'a posée. Trois raisons :
- Le coût. Chaque marché, c'est plusieurs recherches web et plusieurs appels à l'IA. Multipliez par des centaines de marchés en attente, puis par 30 000 communes quand on veut aller plus loin (j'y reviens à la fin) : même à quelques centimes l'appel, la facture grimpe vite. Pour un projet perso, c'est non.
- La recherche web. Les API de recherche de Google ou Bing sont payantes, elles aussi. SearXNG est gratuit et tourne chez moi.
- Le contrôle. Je voulais pouvoir lancer le traitement le soir, le relancer autant de fois que nécessaire pendant la mise au point, sans compter. En local, on ne compte pas.
Mon matériel : un PC portable avec une carte graphique RTX 5060 (8 Go). Rien d'exceptionnel, mais suffisant pour faire tourner un modèle de 8 milliards de paramètres.
Les deux outils
SearXNG est un « méta-moteur » de recherche : il interroge plusieurs moteurs (Google, Bing, DuckDuckGo, Wikipedia...) et renvoie les résultats regroupés, en JSON. On l'installe en une commande avec Docker :
services:
searxng:
image: searxng/searxng:latest
container_name: searxng
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- searxng-config:/etc/searxng
- searxng-cache:/var/cache/searxng
volumes:
searxng-config:
searxng-cache:
docker compose -f docker-compose.searxng.yml up -d
Ollama fait tourner des modèles d'IA (des « LLM ») sur votre machine, avec une API HTTP toute simple. J'utilise qwen3:8b, un modèle compact qui s'en sort très bien en français :
ollama pull qwen3:8b
ollama serve
Et c'est tout pour l'installation. Le reste, c'est du C#.
Le principe, en 4 étapes
Pour chaque marché en attente de validation :
- Chercher les pages qui en parlent (site de la mairie, office de tourisme, presse locale...).
- Garder uniquement les passages utiles de chaque page.
- Demander à l'IA d'en extraire les jours et les horaires.
- Vérifier sa réponse avec du code classique, avant de décider.
1. Chercher avec SearXNG
Une simple requête HTTP, avec format=json :
var requestUri = $"search?q={Uri.EscapeDataString(query)}&format=json&language=fr-FR&safesearch=0";
var response = await client.GetAsync(requestUri, cancellationToken);
La requête ressemble à marché Mauron Morbihan jours et horaires. Si la personne qui a ajouté le marché a indiqué un site web, il est lu en premier, sans même passer par la recherche.
2. Garder les bons passages
Une page de mairie contient beaucoup d'horaires : ceux de la mairie, de la médiathèque, de la piscine... Si on donne toute la page à l'IA, elle risque de se tromper d'horaires (et elle met beaucoup plus de temps à répondre).
Avant tout appel, je découpe donc la page pour ne garder que les passages autour du mot « marché » qui contiennent un jour ou une heure. Une page sans aucun passage de ce type est écartée directement, sans appeler l'IA. C'est simple, et c'est ce qui a le plus accéléré le traitement.
3. Demander à l'IA
L'appel à Ollama tient en quelques lignes :
var request = new
{
model = "qwen3:8b",
prompt,
stream = false,
format = "json", // réponse en JSON, directement désérialisable
think = false, // pas de « réflexion » à voix haute : plus rapide
options = new
{
temperature = 0.1, // le moins de créativité possible
num_ctx = 8192, // taille du contexte (voir les pièges plus bas)
},
};
var response = await client.PostAsJsonAsync("api/generate", request, cancellationToken);
Et le prompt, en résumé :
Trouve dans l'extrait ci-dessous les jours et horaires du marché de {ville}.
Règles :
- Utilise uniquement l'extrait. Ne devine jamais, ne complète jamais des horaires manquants.
- Ignore les autres horaires (mairie, commerces, bibliothèque...) et les autres communes.
- "evidence" doit être copiée mot pour mot depuis l'extrait,
et contenir tous les jours et toutes les heures que tu indiques.
Réponds uniquement avec ce JSON :
{
"scheduleFound": true,
"sessions": [ { "day": "mardi", "start": "08:00", "end": "12:30" } ],
"evidence": "citation exacte",
"confidenceScore": 90
}
Un détail important : je ne donne pas à l'IA les horaires saisis par l'utilisateur. Lors de mes premiers essais, je les lui donnais « pour l'aider »... et elle se contentait de les confirmer ! Maintenant, elle cherche à l'aveugle, et c'est le code qui compare ensuite son résultat avec la saisie.
4. Vérifier (la partie la plus importante)
Un LLM, même bien guidé, peut inventer. Il m'est arrivé d'obtenir un horaire parfaitement plausible... qui n'apparaissait nulle part dans la page.
D'où l'idée qui rend l'outil fiable : l'IA doit fournir une citation exacte (le champ evidence), et du code classique, sans aucune IA, vérifie que :
- la citation existe vraiment dans la page ;
- chaque jour annoncé est bien écrit dans la citation (ou couvert par « du mardi au samedi », « tous les jours »...) ;
- chaque heure annoncée est bien écrite dans la citation.
if (!IsQuotedFrom(extraction.Evidence, pageText))
{
return null; // citation introuvable dans la page : réponse rejetée
}
var quotedDays = FrenchCalendar.ExtractDays(extraction.Evidence);
if (extraction.Sessions.Any(session => !quotedDays.Contains(session.Day)))
{
return null; // un jour qui n'est pas dans la citation : rejeté
}
var quotedTimes = FrenchCalendar.ExtractTimes(extraction.Evidence);
if (extraction.Sessions.Any(s => !quotedTimes.Contains(s.Start!.Value) || !quotedTimes.Contains(s.End!.Value)))
{
return null; // une heure inventée : rejeté
}
Si un contrôle échoue, l'IA a droit à une seconde chance, avec le motif précis du refus (« l'heure 14:00 n'est pas dans ta citation »). Mais les contrôles, eux, ne sont jamais assouplis.
Enfin, chaque source reçoit une note de confiance : 100 pour le site de la mairie, 95 pour l'office de tourisme, 80 pour la presse, 60 pour un annuaire... Un marché n'est publié que si son score atteint 85. En clair : le site de la mairie suffit à lui seul, un annuaire doit être confirmé par une autre source.
Les pièges dans lesquels je suis tombé
La taille du contexte. Par défaut, Ollama limite le contexte à 4 096 tokens, même si le modèle en accepte bien plus. Un extrait un peu long dépassait cette limite : Ollama tronquait le prompt sans prévenir, et l'IA renvoyait un JSON incohérent. Le pire ? Ça touchait surtout les pages les plus riches. Solution : num_ctx = 8192 sur chaque appel.
Les moteurs de recherche n'aiment pas les robots. Après quelques dizaines de requêtes automatiques, Google et consorts bloquent SearXNG. J'ai donc ajouté un délai entre les requêtes et, pour la recherche de nouveaux marchés (j'y reviens plus bas), des sources qui ne passent pas par un moteur : le site officiel de la mairie, retrouvé grâce à l'annuaire de l'administration (service-public.fr, gratuit et sans clé). Pour les communes, le moteur Wikipedia de SearXNG est aussi bien plus tolérant.
Un cache, sinon rien. Chaque recherche, chaque page et chaque réponse d'Ollama sont gardées dans une petite base SQLite. Relancer le traitement après une correction prend quelques secondes au lieu de plusieurs heures.
Un mode « à blanc ». Avec --dry-run, l'outil fait tout le travail mais n'écrit rien en base : il produit seulement le rapport. Indispensable pour mettre au point les règles sans risque.
Les résultats
Sur mon dernier lot de 200 marchés en attente :
- 6 marchés ont été validés et publiés automatiquement, avec une source officielle. Et pour 4 d'entre eux, les horaires trouvés étaient différents de ceux saisis ! Par exemple un marché saisi le dimanche, alors que l'office de tourisme indique « tous les mardis de 8h à 12h ».
- Les autres n'ont pas été publiés automatiquement : source pas assez fiable, horaires introuvables, sources contradictoires, plusieurs créneaux différents...
6 sur 200, ça peut paraître peu. C'est voulu : je préfère un marché non publié qu'un marché faux. Et surtout, les 194 autres ne repartent pas de zéro. L'outil génère un rapport Excel avec, pour chaque marché, ce qu'il a trouvé, la citation exacte, la source et sa décision. La vérification manuelle ne prend plus 5 minutes, mais quelques secondes : je lis la citation, je clique sur la source si j'ai un doute, et je valide dans l'administration du site.
Et puisque l'outil savait chercher un marché... je lui ai aussi demandé d'en découvrir. Il a passé en revue près de 30 000 communes qui n'avaient aucun marché sur le site, dans 88 départements, et il en a ajouté 662, tous confirmés par une source fiable : 640 grâce au site de la mairie lui-même. Avec la même règle : dans le doute, on ne publie pas.
Le coût de tout ça ? 0 €, en dehors de l'électricité du PC portable, qui a tourné quelques soirées.
Ce que je retiens
- Une IA locale suffit largement pour extraire une information précise d'un texte. Pas besoin du plus gros modèle du marché : un modèle de 8 milliards de paramètres sur une carte graphique grand public fait très bien le travail.
- Ne faites jamais confiance aveuglément à l'IA. Demandez-lui de prouver ce qu'elle avance (une citation exacte) et vérifiez avec du code classique. C'est ce qui fait la différence entre une démo et un outil qu'on peut lancer sur des milliers de lignes.
- Préparez le terrain. Lui donner un extrait court et ciblé plutôt qu'une page entière améliore à la fois la vitesse et la qualité des réponses.
- Gardez l'humain dans la boucle, mais pour les cas difficiles seulement. L'outil ne remplace pas ma vérification, il la rend dix fois plus rapide.
Si vous avez un projet perso avec un problème similaire (des données à vérifier, à classer, à enrichir), essayez Ollama : en une après-midi, vous aurez une IA qui tourne chez vous, sans carte bancaire.
Et si vous cherchez un marché près de chez vous, vous savez où aller : ouestlemarche.fr 😉
Une question sur le code ou la mise en place ? N'hésitez pas à me contacter ou à laisser un commentaire !

Commentaires (0)
Aucun commentaire pour le moment. Soyez le premier à commenter !
Laisser un commentaire