Aller au contenu principal

Jouons avec Ollama - Créer un analyseur d'articles de blog avec un LLM local

Un devcontainer Dockerisé avec deux scripts Python : le premier envoie chaque article Markdown à un modèle Ollama local pour générer des tags, le second compare ces tags entre les articles pour suggérer lesquels devraient se lier entre eux. Aucune API cloud, aucun tag manuel.

· 9 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Claude Code
Assistant IA
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Jouons avec Ollama - Créer un analyseur d'articles de blog avec un LLM local

⚡
TL;DR

Un devcontainer qui fait tourner Ollama à côté de deux scripts Python : 01_generate_tags.py lit chaque article Markdown dans data/posts, envoie son contenu à un modèle local et enregistre les tags générés dans un fichier JSON. 02_analyze_and_link.py compare ensuite les tags entre les articles pour suggérer lesquels devraient être reliés, et indique la fréquence de chaque tag dans le corpus. Tout tourne en local — aucune API cloud, aucun tag manuel.

Tagger ses articles à la main, ça ne passe pas à l'échelle — et repérer, parmi quelques centaines d'articles, ceux qui vont réellement ensemble non plus. Je voulais voir si un modèle local, avec pour seule entrée le Markdown brut, pouvait générer des tags corrects puis utiliser ces tags pour suggérer lui-même des liens internes.

Le résultat​

Une fois les deux scripts exécutés, output/all_articles_with_tags.json contient les tags générés pour chaque article :

Les tags générés

Le deuxième script compare ensuite ces tags entre les articles. suggested_interlinks.json est la première sortie intéressante :

[
{
"source_article": "001-intro-to-docker.md",
"suggested_links": []
},
{
"source_article": "004-local-llms-future.md",
"suggested_links": ["002-getting-started-with-ollama.md"]
},
{
"source_article": "003-advanced-python.md",
"suggested_links": []
},
{
"source_article": "002-getting-started-with-ollama.md",
"suggested_links": ["004-local-llms-future.md"]
}
]

Ce fichier JSON contient un tableau de quatre objets, chacun représentant un article avec son identifiant source et une liste de liens suggérés vers d'autres articles. Cela structure probablement des données de navigation ou de recommandation pour un système documentaire, où certains articles sont liés entre eux (par exemple, l'article sur Ollama et celui sur les LLMs locaux se référencent mutuellement).

Les articles 002 et 004 sont correctement identifiés comme liés — ils parlent tous les deux de LLM locaux. Les articles 001 et 003 sont laissés de côté, puisqu'ils traitent de sujets sans rapport. Plutôt pas mal !

Le second fichier de sortie, tag_analysis.json, montre les tags et leur nombre d'occurrences dans les articles. Sur ce petit échantillon, « local LLMs » apparaît dans deux articles (002 et 004) alors que tous les autres tags n'apparaissent qu'une seule fois :

{
"total_unique_tags": 23,
"top_tags": [
{
"tag": "local",
"count": 2
},
{
"tag": "LLMs",
"count": 2
},
{
"tag": "docker",
"count": 1
},
{
"tag": "containers",
"count": 1
},
{
"tag": "images",
"count": 1
},
{
"tag": "compose",
"count": 1
},
{
"tag": "future",
"count": 1
},
{
"tag": "AI",
"count": 1
},
{
"tag": "development",
"count": 1
},
{
"tag": "advanced",
"count": 1
},
{
"tag": "python",
"count": 1
},
{
"tag": "scripting",
"count": 1
},
{
"tag": "decorators",
"count": 1
},
{
"tag": "generators",
"count": 1
},
{
"tag": "context",
"count": 1
},
{
"tag": "managers",
"count": 1
},
{
"tag": "rest",
"count": 1
},
{
"tag": "api",
"count": 1
},
{
"tag": "language models",
"count": 1
},
{
"tag": "Ollama",
"count": 1
}
]
}

Ce fichier JSON contient des statistiques sur les tags utilisés dans une collection de ressources. Il indique qu'il y a 23 tags uniques au total, et présente une liste des tags les plus fréquents avec leur nombre d'occurrences, où « local » et « LLMs » apparaissent deux fois chacun tandis que les autres tags n'apparaissent qu'une seule fois.

Pourquoi ça fonctionne​

  • Un script par responsabilité : le premier script ne parle qu'au LLM et produit des tags ; le second se contente de lire ces tags et de calculer les relations — aucun script ne fait les deux.
  • Les tags sont le seul signal utilisé pour les liens. Deux articles partageant un tag sont considérés comme liés ; plus ils partagent de tags, plus la suggestion est forte.
  • Rien ici n'est spécifique à Docusaurus — remplacez data/posts par n'importe quel dossier de fichiers Markdown et les deux mêmes scripts produisent le même type d'analyse.

Installation​

Copier la structure de répertoires et les fichiers​

Lancez la commande suivante dans votre terminal pour copier la structure de répertoires et les fichiers de ce tutoriel :

📦 Mise en place du projet : /tmp/tags
Aide

Besoin d'aide ? Cliquez sur le bouton « Aide » ci-dessus pour les instructions de mise en place.

Une fois terminé, lancez code . pour ouvrir le répertoire courant dans Visual Studio Code puis appuyez sur Ctrl+Shift+P et choisissez Devcontainers: Reopen in Container pour ouvrir le projet dans un container de développement.

Le build du container et l'installation des dépendances prendront quelques minutes. Une fois le devcontainer démarré, vous verrez dans Docker Desktop que les deux containers tournent :

Les containers tournent

Télécharger le modèle LLM​

Revenez ensuite à votre terminal (sur votre host) et lancez la commande suivante pour télécharger le modèle LLM :

>user@machine: ~/yourproject

$ docker exec -it tags-ollama-1 ollama pull llama3:8b

Télécharger le modèle LLM

Tester le service Ollama​

Nous venons de télécharger le modèle LLM, vérifions maintenant que le service Ollama fonctionne correctement. Lancez la commande suivante dans votre terminal (sur votre host) :

>user@machine: ~/yourproject

$ curl --silent http://localhost:11444/api/tags | jq

Test du service Ollama

Si vous n'avez pas jq

La commande jq sert à formater la sortie JSON pour la rendre plus lisible. Si jq n'est pas installé chez vous, consultez L'utilitaire jq pour Linux pour apprendre à l'installer et à l'utiliser, ou lancez simplement la commande curl sans lui pour voir la réponse JSON brute.

curl --silent http://localhost:11444/api/generate \
-d '{\
"model": "llama3:8b", \
"prompt": "Explain in one sentence why Docker is so amazing.", \
"stream": false \
}' | jq .response

Pourquoi Docker est génial ?

Le service fonctionne, et on voit que l'endpoint tags est disponible. C'est cet endpoint que nos scripts Python utiliseront pour envoyer le contenu des articles et récupérer les tags générés.

Autres démos​

Lancer le script de génération de tags​

Retournez dans Visual Studio Code, ouvrez le terminal (dans VSCode) et exécutez le fichier scripts/01_generate_tags.py. Ce script lit tous les fichiers Markdown du répertoire data/posts, envoie leur contenu au modèle LLM qui tourne dans le container, et enregistre les tags générés dans un fichier JSON.

Exécution du script de génération de tags

Et effectivement, vous constatez que le fichier output/all_articles_with_tags.json a été créé — les tags montrés plus haut dans « Le résultat » sont exactement ce que cette exécution a produit.

Port de l'host vs port du container

Remarquez que scripts/01_generate_tags.py appelle http://ollama:11434/api/generate, et non http://ollama:11444/api/generate comme les commandes curl ci-dessus.

Sur votre host, curl doit utiliser 11444 — le port publié par compose.yaml ("11444:11434"). Mais 01_generate_tags.py tourne à l'intérieur du container app, sur le même réseau Docker Compose qu'ollama. De là, 11444 n'existe pas : sur ce réseau, les containers se joignent via le port du container lui-même, 11434. Mélanger le nom du service (résolvable uniquement à l'intérieur du réseau Compose) et le port publié sur l'host est un piège classique, et ça se termine par un Connection refused.

Le second script, scripts/02_analyze_and_link.py, lit les tags générés depuis ce fichier JSON et produit les fichiers suggested_interlinks.json et tag_analysis.json montrés plus haut.

Exécution du script d'analyse et de liens

Sous le capot (à sauter si vous voulez juste l'utiliser)​

Choisir le bon modèle​

Dans cet article, j'ai pris llama3:8b comme point de départ. Mais la vraie force d'Ollama, c'est la possibilité de changer de « cerveau » selon la tâche. Le registre Ollama propose une immense bibliothèque de modèles, mais le bon choix dépend de votre matériel — en particulier de votre RAM et de votre GPU.

Comparaison des modèles en un coup d'œil​

ModèleCas d'usage idéalAvantagesInconvénientsMatériel requis
Llama 3 (8B)Discussion informelle, scripts simples, tâches rapides.Extrêmement rapide, léger, tourne presque partout.Capacité de raisonnement plus faible sur la logique complexe.~8 Go de RAM
Mistral (7B)Code, écriture créative, raisonnement général.Souvent plus « humain » et plus concis.Peut être moins rigoureux que Llama 3 sur les données structurées.~8 Go de RAM
Llama 3 (70B)Analyse approfondie, code complexe, raisonnement lourd.Intelligence proche de l'humain, très peu d'hallucinations.Gourmand en ressources ; génération plus lente.~48 Go de RAM et plus

Lequel choisir ?​

  • Prenez llama3:8b si vous débutez ou si votre RAM est limitée. Il est parfait pour du prototypage rapide et des tâches d'automatisation simples qui ne demandent pas de raisonnement logique poussé.
  • Essayez mistral si vous trouvez les réponses de Llama 3 un peu trop rigides. Beaucoup de développeurs préfèrent Mistral pour son côté créatif et son efficacité. C'est un excellent modèle « du quotidien » pour l'aide au code en général.
  • Passez à llama3:70b si vous faites des tâches qui exigent une grande précision — refactoring de bases de code complexes, débogage logique poussé, ou traitement de gros jeux de données où la justesse est critique. Ce modèle étant énorme, il réduit fortement les « hallucinations », ce qui en fait le choix le plus fiable pour un travail professionnel.

Télécharger vos modèles​

Vous pouvez ajouter n'importe lequel de ces modèles à votre environnement local immédiatement. Lancez simplement les commandes suivantes dans votre terminal :

Pour récupérer le modèle standard Llama 3 (8B) :

>user@machine: ~/yourproject

$ docker exec -it tags-ollama-1 ollama pull llama3:8b

Pour récupérer le très performant Llama 3 (70B) :

>user@machine: ~/yourproject

$ docker exec -it tags-ollama-1 ollama pull llama3:70b

Pour récupérer le modèle Mistral :

>user@machine: ~/yourproject

$ docker exec -it tags-ollama-1 ollama pull mistral

Note : le modèle 70b est bien plus gros (~40 Go). Assurez-vous d'avoir assez d'espace disque et, surtout, au moins 48 Go de RAM disponibles pour que le modèle tourne sans ralentir votre système.

Pas assez de RAM ?

Sur ma machine avec 64 Go de RAM, je peux faire tourner le modèle 70b, mais il consomme beaucoup de ressources. Avec moins de RAM, mieux vaut rester sur 8b ou mistral pour une expérience plus fluide.

Conclusion​

Deux petits scripts Python et un modèle local ont transformé un dossier d'articles Markdown en un index de tags et une série de suggestions de liens internes — aucune API cloud, aucun tag manuel, et rien dans ce pipeline n'est spécifique à Docusaurus. Faites pointer data/posts vers n'importe quel dossier de fichiers Markdown et les deux mêmes scripts feront le même travail.

Transformer une suggestion du type « les articles 002 et 004 sont liés » en un vrai <Link> dans le texte reste ici une étape manuelle — la suite logique, c'est que le second script propose la phrase exacte et le texte du lien, et pas seulement la paire de fichiers.


🦋 Rejoignez la conversation sur BlueskyUn compte Bluesky gratuit est nécessaire pour aimer, repartager ou commenter. Ce bloc interroge l'API publique de Bluesky directement depuis votre navigateur (sans cookie, sans connexion) — votre adresse IP parvient donc aux serveurs de Bluesky dès que cette section se charge.

Chargement des commentaires…

Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?