Aller au contenu principal

Automatiser les résumés TL;DR avec Gemini AI

Améliorez l'expérience de vos lecteurs en générant automatiquement des résumés TL;DR concis pour vos articles de blog avec Gemini AI de Google et Python.

· 7 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
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.
Cet article fait partie de la série Créer des composants Docusaurus :

Automatiser les résumés TL;DR avec Gemini AI

⚡
TL;DR

Écrire des résumés pour de longs articles améliore l'expérience utilisateur, mais ça prend du temps. Cet article explique comment automatiser la génération de sections « Too Long; Didn't Read » (TL;DR) avec un script Python et Gemini AI de Google. Nous verrons la mise en place Docker, l'utilisation du script et son intégration dans votre workflow Docusaurus.

En tant que blogueur technique, je cherchais un moyen d'améliorer l'expérience de mes lecteurs en proposant des résumés concis au début de mes articles — pour qu'ils ne perdent pas leur temps (j'espère !) à lire un article entier avant de se dire : « Attends, ce n'est pas ce que je cherchais. »

J'ai donc décidé d'automatiser la génération de résumés TL;DR avec Gemini AI de Google et un simple script Python. Dans cet article, je vous explique comment j'ai fait.

Ce n'est pas mon seul usage de Gemini sur ce blog : lisez Comment j'ai utilisé Google Gemini Nano Banana sur mon blog pour le volet illustrations de l'histoire.

Avant et après​

Le script prend un article entier — chaque paragraphe, chaque titre — et le réduit à quelques phrases. Voici un exemple réel, tiré directement de l'article sur Lovable.dev de ce blog.

Avant — les premiers paragraphes que le script lit réellement :

Cette semaine, un collègue m'a parlé de Lovable.dev en me disant : « Dans un prompt, il suffit de décrire le programme que vous voulez générer, et l'outil le construit et le déploie même pour vous ». Waouh, il fallait absolument que j'essaie.

Mais que demander ? Et si je lui demandais de créer un clone de Marknotes ? Ceux qui me suivent depuis des années savent que j'ai créé Marknotes, une application de prise de notes, il y a 10 ans. J'y ai travaillé pendant cinq ans avant de passer à autre chose.

Voyons si Lovable.dev peut construire la même chose en une seule heure. Spoiler : non, mais ce n'était pas si mal.

Après — le <TLDR> que le script a généré et injecté en haut de ce même article :

Le TLDR généré, tel qu&#39;il s&#39;affiche sur l&#39;article publié

La même densité d'information dont les lecteurs ont vraiment besoin, en une fraction du temps de lecture.

Le concept​

L'idée est simple : il me faut un script qui parcourt mes articles de blog (un ou plusieurs) et génère un court résumé avec Gemini AI. Ensuite, il doit insérer ce résumé dans l'article, enveloppé dans un composant <TLDR> maison pour le style et la visibilité.

Le script va faire ceci :

  1. Recevoir un chemin en entrée (fichier ou dossier).
  2. Lire les fichiers Markdown.
  3. Envoyer le contenu à Gemini AI pour résumé.
  4. Récupérer le résumé.
  5. Réinjecter le résumé dans le fichier Markdown.

Ma structure de dossiers ressemble à ceci : blog/YYYY/MM/DD/index.md pour chaque article. Donc en appelant le script avec blog/2026/01/, il traitera tous les articles de janvier 2026.

Le composant React​

D'abord, il nous faut une façon d'afficher joliment le résumé dans Docusaurus. J'utilise un simple composant maison pour ça. Voici l'implémentation :

<TLDR> This is the summary of the article... </TLDR>

Le code du composant est le suivant :

import { useMemo, type JSX, type ReactNode } from "react";
import Head from "@docusaurus/Head";
import MobileQuickLinks from "@site/src/components/Blog/MobileQuickLinks";
import styles from "./styles.module.css";
import { translate } from "@docusaurus/Translate";
// Recursively extracts plain text from React nodes for JSON-LD abstract
function extractText(node: unknown): string {
if (typeof node === "string") return node;
if (typeof node === "number") return String(node);
if (Array.isArray(node)) return node.map(extractText).join("");
if (node && typeof node === "object") {
const children = (node as { props?: { children?: unknown } }).props?.children;
if (children) return extractText(children);
}
return "";
}
interface Props {
children: ReactNode;
}
// Injects JSON-LD so search engines read the abstract via Schema.org BlogPosting
export default function TLDR({ children }: Props): JSX.Element {
const structuredData = useMemo(
() => ({
"@context": "https://schema.org",
"@type": "BlogPosting",
abstract: extractText(children),
}),
[children],
);
return (
<>
<Head>
<script type="application/ld+json">{JSON.stringify(structuredData)}</script>
</Head>
<div
className={styles.tldrContainer}
role="region"
aria-label={translate({ id: "tldr.ariaLabel", message: "Article Summary" })}
>
<span
role="img"
aria-label={translate({ id: "tldr.iconLabel", message: "lightning" })}
className={styles.tldrIcon}
>
⚡
</span>
<div className={styles.tldrBody}>
<strong className={styles.tldrTitle}>TL;DR</strong>
<div className={styles.tldrContent}>{children}</div>
</div>
</div>
{/*
The TL;DR is the one block every post opens with, which makes it the only reliable
anchor for a "read next" hint placed *after* the reader has confirmed the article is
the right one. MobileQuickLinks decides on its own whether it has anything to show.
*/}
<MobileQuickLinks />
</>
);
}

This React component creates a 'TL;DR' (summary) section for blog posts that displays user-provided content while also inserting JSON-LD structured data into the page head so search engines understand the summary is an abstract. It recursively extracts plain text from the React children to populate the structured data, and includes accessibility labels so screen readers know what the section is.

/*
* TL;DR — was borrowing Infima's "alert alert--info" utility classes, which is
* where its unexplained Docusaurus blue came from. The summary is the first
* block of every article on the site: it should carry the site's own colour,
* not a framework default.
*/
.tldrContainer {
composes: mk-callout from global;
composes: mk-callout--key from global;
}
/*
* font-variant-emoji: text asks for the monochrome TEXT presentation of the
* lightning character, so it takes --mk-on-line from .mk-dot like every other
* dot glyph in the site. Without it the emoji keeps its own yellow-blue
* colours on the terracotta disc — the one bicolour pastille on the page.
* index.tsx needs no change.
*/
.tldrIcon {
composes: mk-dot from global;
font-size: 0.9rem;
font-variant-emoji: text;
}
.tldrBody {
min-width: 0;
}
.tldrTitle {
composes: mk-eyebrow from global;
display: block;
margin-bottom: 0.25rem;
color: inherit;
}
/*
* The old rule indented the summary by a hardcoded 2.5rem to clear the icon,
* and dimmed it with opacity: 0.9. Both are gone: the flex row aligns the text
* for free, and a summary is the last thing on the page that should be faded.
*/
.tldrContent {
font-size: 0.95rem;
line-height: 1.65;
}
.tldrContent > :last-child {
margin-bottom: 0;
}
.tldrContent a {
color: var(--tone-line);
text-decoration: underline;
text-underline-offset: 2px;
}

This CSS file styles a summary box component that appears at the start of articles. It composes several base utility classes to inherit their styling, then customizes the appearance of the icon, title, and body text to match the site's design system rather than using default framework colors.

Le script d'automatisation​

Sur mon blog, j'ai créé un dossier .scripts/python_tldr pour héberger le script Python et ses dépendances.

API Gemini

Il vous faudra une clé d'API Google Gemini pour que ça fonctionne. Vous pouvez en obtenir une sur https://aistudio.google.com/api-keys.

Exécution avec Docker​

Comme je suis un grand fan de Docker, je voulais m'assurer que le script tourne dans un environnement reproductible.

Voici comment démarrer le container :

>user@machine: ~/yourproject

Cette commande va créer un container Python, monter votre répertoire courant sur /app, lire et charger votre fichier d'environnement, installer les packages nécessaires (google-genai pour l'accès à l'API Gemini et python-dotenv pour la gestion des variables d'environnement), puis lancer un shell bash où vous pourrez exécuter le script.

Variables d'environnement

Vous devrez créer un fichier .env à la racine de votre projet avec le contenu suivant :

GOOGLE_API_KEY=your_gemini_api_key_here

Ce script configure une variable d'environnement GOOGLE_API_KEY avec une clé d'API Gemini. Cette variable sera utilisée par d'autres parties du script ou d'autres programmes pour s'authentifier auprès des services Google.

Générer les résumés​

Une fois dans le container, vous pouvez lancer le script sur un fichier précis ou sur tout un répertoire.

Pour traiter un seul fichier :

>user@machine: ~/yourproject

Pour traiter tous les articles d'un mois donné :

>user@machine: ~/yourproject

Le script est assez malin pour ignorer les fichiers qui contiennent déjà un tag <TLDR>, vous pouvez donc le lancer sans risque sur toute l'archive de votre blog.

Soyez transparent avec vos lecteurs

Un résumé écrit par une machine reste du contenu généré par une machine. Je le signale explicitement sur chaque article concerné ; voir Comment signaler un contenu assisté par IA dans un blog Docusaurus.

Le même principe — générer une fois à l'écriture, committer le résultat — est réutilisé dans AI-Powered Code Tooltips in Docusaurus : les lecteurs n'attendent jamais un appel d'API et votre clé ne quitte jamais votre machine.

Erreur - 429 RESOURCE_EXHAUSTED​

Cette erreur indique que vous avez dépassé vos limites d'utilisation de l'API Gemini. Selon votre plan, il peut y avoir des restrictions sur le nombre de requêtes ou sur le volume de données traitables dans un intervalle de temps donné.

Le plan gratuit est assez limité : si vous avez beaucoup d'articles, envisagez de passer à un plan supérieur ou de lancer le script par lots pour éviter d'atteindre la limite.

Vous pouvez toujours utiliser la même fonctionnalité, mais manuellement : allez sur https://gemini.google.com/app, collez le contenu de votre article et demandez à Gemini de générer un résumé TL;DR. Copiez ensuite le résultat et collez-le dans votre article, à l'intérieur du composant <TLDR>.

Voici le prompt utilisé pour obtenir le résumé :

You are an expert technical editor.

Read the following article content and generate a 'TL;DR' summary.

The summary must be concise (max 3 sentences) and written in the same language as the article.

Conclusion​

Vous trouverez ci-dessous tous les fichiers nécessaires pour mettre ça en place sur votre propre blog Docusaurus. N'hésitez pas à adapter et améliorer le script selon vos besoins !

📦 Mise en place du projet : /your_docusaurus_site
Aide

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

Limitations de Gemini

Selon votre plan Gemini AI, il peut y avoir des limites sur le nombre de requêtes ou la longueur du texte traité. Vérifiez bien les détails de votre plan pour éviter les frais inattendus ou les interruptions.

Actuellement, mon propre plan me permet de faire 20 appels par jour.

src/theme/MDXComponents.js

N'oubliez pas de mettre à jour votre fichier src/theme/MDXComponents.js pour y inclure le nouveau composant TLDR, afin que Docusaurus sache comment le rendre. Si vous n'avez pas encore ce fichier, créez-le. Voici son contenu :


Cet article fait partie de la série Créer des composants Docusaurus :
🦋 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 ?