Créer des applications IA avec Google Gemini API et TypeScript

Google Gemini 2.5 Pro est arrivé. Avec une fenêtre de contexte de 1 million de tokens, des capacités multimodales natives et des appels de fonctions intégrés, Gemini est une des API IA les plus puissantes disponibles aujourd'hui. Dans ce tutoriel, vous apprendrez à exploiter tout son potentiel avec TypeScript.
Ce que vous apprendrez
À la fin de ce tutoriel, vous serez capable de :
- Configurer le SDK Google Generative AI dans un projet TypeScript
- Générer du texte avec Gemini 2.5 Pro et Gemini 2.5 Flash
- Traiter des images, des PDF et de l'audio avec des entrées multimodales
- Implémenter le streaming de réponses en temps réel
- Utiliser les appels de fonctions pour connecter Gemini à des outils externes
- Extraire des données structurées avec un schéma JSON
- Construire un assistant IA pratique avec historique de conversation
Prérequis
Avant de commencer, assurez-vous d'avoir :
- Node.js 20+ installé (
node --version) - Des connaissances en TypeScript (types, async/await, modules)
- Une clé API Google AI Studio — obtenez-en une gratuitement sur aistudio.google.com
- Un éditeur de code — VS Code ou Cursor recommandé
- Une compréhension basique des API REST et de la programmation asynchrone
Étape 1 : Configuration du projet
Créez un nouveau projet TypeScript et installez le SDK Google Generative AI :
mkdir gemini-ai-app && cd gemini-ai-app
npm init -y
npm install @google/generative-ai
npm install -D typescript @types/node tsxInitialisez TypeScript :
npx tsc --init --target ES2022 --module NodeNext --moduleResolution NodeNext --outDir dist --rootDir src --strictCréez la structure du projet :
mkdir src
touch src/index.ts .envAjoutez votre clé API dans .env :
GEMINI_API_KEY=your_api_key_hereMettez à jour les scripts de package.json :
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
}Étape 2 : Votre première génération de texte
Commençons par un exemple simple de génération de texte. Créez src/index.ts :
import { GoogleGenerativeAI } from "@google/generative-ai";
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
async function generateText() {
const model = genAI.getGenerativeModel({
model: "gemini-2.5-pro",
});
const result = await model.generateContent(
"Expliquez l'informatique quantique en 3 phrases pour un développeur logiciel."
);
console.log(result.response.text());
}
generateText();Exécutez-le :
GEMINI_API_KEY=your_key tsx src/index.tsVous devriez voir une explication concise de l'informatique quantique. La méthode generateContent envoie une requête unique et retourne la réponse complète.
Comprendre l'objet Response
La réponse contient plus que du texte :
async function inspectResponse() {
const model = genAI.getGenerativeModel({ model: "gemini-2.5-pro" });
const result = await model.generateContent("Bonjour, Gemini !");
const response = result.response;
console.log("Texte:", response.text());
console.log("Utilisation:", response.usageMetadata);
// { promptTokenCount: 4, candidatesTokenCount: 12, totalTokenCount: 16 }
}Le champ usageMetadata vous aide à suivre la consommation de tokens pour la gestion des coûts.
Étape 3 : Choisir le bon modèle
Gemini propose plusieurs modèles optimisés pour différents cas d'utilisation :
| Modèle | Idéal pour | Fenêtre de contexte | Vitesse |
|---|---|---|---|
gemini-2.5-pro | Raisonnement complexe, codage, analyse | 1M tokens | Modérée |
gemini-2.5-flash | Réponses rapides, haut débit | 1M tokens | Rapide |
gemini-2.5-flash-lite | Économique, tâches simples | 1M tokens | La plus rapide |
// Pour les analyses complexes
const pro = genAI.getGenerativeModel({ model: "gemini-2.5-pro" });
// Pour les applications nécessitant de la vitesse
const flash = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
// Pour les tâches simples à grand volume
const lite = genAI.getGenerativeModel({ model: "gemini-2.5-flash-lite" });Conseil : Commencez avec gemini-2.5-flash pour le développement. Passez à pro uniquement quand vous avez besoin de ses capacités de raisonnement améliorées. Flash est nettement moins cher et plus rapide.
Étape 4 : Entrées multimodales — Images et PDF
L'une des fonctionnalités les plus puissantes de Gemini est sa compréhension multimodale native. Vous pouvez envoyer des images, des PDF, de l'audio et de la vidéo avec du texte.
Analyser une image
import { GoogleGenerativeAI } from "@google/generative-ai";
import * as fs from "fs";
import * as path from "path";
async function analyzeImage(imagePath: string) {
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
const imageData = fs.readFileSync(imagePath);
const base64Image = imageData.toString("base64");
const mimeType = imagePath.endsWith(".png") ? "image/png" : "image/jpeg";
const result = await model.generateContent([
{
inlineData: {
mimeType,
data: base64Image,
},
},
"Décrivez cette image en détail. Quels objets, couleurs et scènes voyez-vous ?",
]);
console.log(result.response.text());
}
analyzeImage("./sample-image.jpg");Traiter un document PDF
async function analyzePDF(pdfPath: string) {
const model = genAI.getGenerativeModel({ model: "gemini-2.5-pro" });
const pdfData = fs.readFileSync(pdfPath);
const base64PDF = pdfData.toString("base64");
const result = await model.generateContent([
{
inlineData: {
mimeType: "application/pdf",
data: base64PDF,
},
},
"Résumez les points clés de ce document. Listez les sujets principaux et les actions à entreprendre.",
]);
console.log(result.response.text());
}Comparer plusieurs images
async function compareImages(image1Path: string, image2Path: string) {
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
const image1 = fs.readFileSync(image1Path).toString("base64");
const image2 = fs.readFileSync(image2Path).toString("base64");
const result = await model.generateContent([
{ inlineData: { mimeType: "image/jpeg", data: image1 } },
{ inlineData: { mimeType: "image/jpeg", data: image2 } },
"Comparez ces deux images. Quelles sont les différences et les similitudes ?",
]);
console.log(result.response.text());
}Étape 5 : Streaming des réponses
Pour une meilleure expérience utilisateur, diffusez les réponses token par token au lieu d'attendre la réponse complète :
async function streamResponse(prompt: string) {
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
const result = await model.generateContentStream(prompt);
process.stdout.write("Gemini: ");
for await (const chunk of result.stream) {
const text = chunk.text();
process.stdout.write(text);
}
console.log("\n");
// Accéder à la réponse agrégée après le streaming
const aggregated = await result.response;
console.log("Total tokens:", aggregated.usageMetadata?.totalTokenCount);
}
streamResponse("Écrivez un court poème sur TypeScript.");Streaming dans un serveur web
Voici comment intégrer le streaming avec un serveur HTTP simple :
import { createServer } from "http";
const server = createServer(async (req, res) => {
if (req.method === "POST" && req.url === "/chat") {
const body = await getBody(req);
const { message } = JSON.parse(body);
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
const result = await model.generateContentStream(message);
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
for await (const chunk of result.stream) {
res.write(`data: ${JSON.stringify({ text: chunk.text() })}\n\n`);
}
res.write("data: [DONE]\n\n");
res.end();
}
});
server.listen(3000, () => console.log("Serveur en cours sur le port 3000"));
function getBody(req: any): Promise<string> {
return new Promise((resolve) => {
let body = "";
req.on("data", (chunk: string) => (body += chunk));
req.on("end", () => resolve(body));
});
}Étape 6 : Appels de fonctions
Les appels de fonctions permettent à Gemini d'invoquer vos fonctions TypeScript pour récupérer des données en temps réel, interagir avec des API ou effectuer des calculs.
Définir les outils
import {
GoogleGenerativeAI,
FunctionDeclarationSchemaType,
} from "@google/generative-ai";
const tools = [
{
functionDeclarations: [
{
name: "getWeather",
description:
"Obtenir la météo actuelle pour un lieu spécifique",
parameters: {
type: FunctionDeclarationSchemaType.OBJECT,
properties: {
location: {
type: FunctionDeclarationSchemaType.STRING,
description: "Nom de la ville, ex: 'Tunis' ou 'Paris'",
},
unit: {
type: FunctionDeclarationSchemaType.STRING,
enum: ["celsius", "fahrenheit"],
description: "Unité de température",
},
},
required: ["location"],
},
},
{
name: "searchProducts",
description: "Rechercher des produits dans le catalogue",
parameters: {
type: FunctionDeclarationSchemaType.OBJECT,
properties: {
query: {
type: FunctionDeclarationSchemaType.STRING,
description: "Requête de recherche",
},
maxPrice: {
type: FunctionDeclarationSchemaType.NUMBER,
description: "Filtre de prix maximum",
},
},
required: ["query"],
},
},
],
},
];Gérer les appels de fonctions
// Implémentations de fonctions simulées
function getWeather(location: string, unit = "celsius") {
const mockData: Record<string, { temp: number; condition: string }> = {
tunis: { temp: 24, condition: "Ensoleillé" },
paris: { temp: 15, condition: "Nuageux" },
tokyo: { temp: 20, condition: "Dégagé" },
};
const data = mockData[location.toLowerCase()] || {
temp: 20,
condition: "Inconnu",
};
return {
location,
temperature: data.temp,
unit,
condition: data.condition,
};
}
function searchProducts(query: string, maxPrice?: number) {
return {
results: [
{ name: `${query} Pro`, price: 99.99, rating: 4.5 },
{ name: `${query} Lite`, price: 49.99, rating: 4.2 },
].filter((p) => !maxPrice || p.price <= maxPrice),
};
}
async function chatWithTools(userMessage: string) {
const model = genAI.getGenerativeModel({
model: "gemini-2.5-flash",
tools,
});
const chat = model.startChat();
const result = await chat.sendMessage(userMessage);
const response = result.response;
const functionCalls = response.functionCalls();
if (functionCalls && functionCalls.length > 0) {
const functionResponses = functionCalls.map((call) => {
let result;
switch (call.name) {
case "getWeather":
result = getWeather(
call.args.location as string,
call.args.unit as string
);
break;
case "searchProducts":
result = searchProducts(
call.args.query as string,
call.args.maxPrice as number
);
break;
default:
result = { error: "Fonction inconnue" };
}
return {
functionResponse: {
name: call.name,
response: result,
},
};
});
// Renvoyer les résultats des fonctions à Gemini
const finalResult = await chat.sendMessage(functionResponses);
console.log(finalResult.response.text());
} else {
console.log(response.text());
}
}
chatWithTools("Quelle est la météo à Tunis et trouvez-moi des options de laptop à moins de 80$ ?");Gemini appellera les deux fonctions en parallèle et synthétisera les résultats en une réponse en langage naturel.
Étape 7 : Sorties structurées avec schéma JSON
Forcez Gemini à retourner des données dans une structure JSON spécifique — idéal pour construire des pipelines de données fiables :
async function extractStructuredData(text: string) {
const model = genAI.getGenerativeModel({
model: "gemini-2.5-flash",
generationConfig: {
responseMimeType: "application/json",
responseSchema: {
type: FunctionDeclarationSchemaType.OBJECT,
properties: {
sentiment: {
type: FunctionDeclarationSchemaType.STRING,
enum: ["positive", "negative", "neutral"],
},
confidence: {
type: FunctionDeclarationSchemaType.NUMBER,
},
topics: {
type: FunctionDeclarationSchemaType.ARRAY,
items: {
type: FunctionDeclarationSchemaType.STRING,
},
},
summary: {
type: FunctionDeclarationSchemaType.STRING,
},
},
required: ["sentiment", "confidence", "topics", "summary"],
},
},
});
const result = await model.generateContent(
`Analysez le texte suivant :\n\n${text}`
);
const data = JSON.parse(result.response.text());
return data;
}
// Utilisation
const analysis = await extractStructuredData(
"La nouvelle API Gemini est incroyable ! La documentation est claire, " +
"le SDK TypeScript est bien conçu, et les tarifs sont très compétitifs. " +
"Cependant, les limites de débit peuvent être préoccupantes pour les applications à fort trafic."
);
console.log(analysis);
// {
// sentiment: "positive",
// confidence: 0.85,
// topics: ["API", "documentation", "SDK", "tarification", "limites de débit"],
// summary: "Avis positif sur Gemini API avec une préoccupation mineure sur les limites de débit"
// }Étape 8 : Construire un assistant IA conversationnel
Rassemblons tout dans un assistant IA pratique avec historique de conversation, instructions système et paramètres de sécurité :
import {
GoogleGenerativeAI,
HarmCategory,
HarmBlockThreshold,
} from "@google/generative-ai";
import * as readline from "readline";
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
async function startAssistant() {
const model = genAI.getGenerativeModel({
model: "gemini-2.5-flash",
systemInstruction: `Vous êtes un assistant de programmation spécialisé en TypeScript et Node.js.
Vous fournissez des réponses concises et pratiques avec des exemples de code quand c'est approprié.
Vous considérez toujours les meilleures pratiques et les implications de sécurité.
Si vous n'êtes pas sûr de quelque chose, dites-le plutôt que de deviner.`,
safetySettings: [
{
category: HarmCategory.HARM_CATEGORY_HARASSMENT,
threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
},
{
category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
},
],
generationConfig: {
temperature: 0.7,
topP: 0.95,
topK: 40,
maxOutputTokens: 2048,
},
});
const chat = model.startChat({
history: [],
});
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
console.log("Assistant IA prêt ! Tapez 'exit' pour quitter.\n");
const askQuestion = () => {
rl.question("Vous: ", async (input) => {
const trimmed = input.trim();
if (trimmed.toLowerCase() === "exit") {
console.log("Au revoir !");
rl.close();
return;
}
try {
const result = await chat.sendMessageStream(trimmed);
process.stdout.write("Assistant: ");
for await (const chunk of result.stream) {
process.stdout.write(chunk.text());
}
console.log("\n");
} catch (error: any) {
console.error("Erreur:", error.message);
}
askQuestion();
});
};
askQuestion();
}
startAssistant();Explication de la configuration de génération
| Paramètre | Par défaut | Description |
|---|---|---|
temperature | 1.0 | Contrôle le hasard. Plus bas = plus concentré, plus haut = plus créatif |
topP | 0.95 | Échantillonnage par noyau. Considère les tokens avec probabilité cumulative jusqu'à cette valeur |
topK | 40 | Ne considère que les K tokens les plus probables à chaque étape |
maxOutputTokens | Variable | Nombre maximum de tokens à générer |
Étape 9 : Gestion des erreurs et limitation de débit
Les applications en production nécessitent une gestion robuste des erreurs :
import { GoogleGenerativeAI, GoogleGenerativeAIError } from "@google/generative-ai";
async function safeGenerate(prompt: string, retries = 3): Promise<string> {
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const result = await model.generateContent(prompt);
return result.response.text();
} catch (error: any) {
const status = error?.status;
if (status === 429) {
// Limite de débit atteinte — backoff exponentiel
const delay = Math.pow(2, attempt) * 1000;
console.warn(
`Limite de débit atteinte. Nouvelle tentative dans ${delay / 1000}s (tentative ${attempt}/${retries})`
);
await new Promise((r) => setTimeout(r, delay));
continue;
}
if (status === 400) {
console.error("Requête invalide — vérifiez votre prompt ou vos paramètres");
throw error;
}
if (status === 403) {
console.error("Clé API invalide ou quota dépassé");
throw error;
}
if (attempt === retries) throw error;
console.warn(`Erreur (tentative ${attempt}/${retries}):`, error.message);
await new Promise((r) => setTimeout(r, 1000 * attempt));
}
}
throw new Error("Nombre maximum de tentatives dépassé");
}Bonnes pratiques pour les limites de débit
- Utilisez le backoff exponentiel — doublez le temps d'attente entre les tentatives
- Mettez les réponses en cache — stockez les résultats pour des prompts identiques
- Utilisez Flash pour le haut volume — il a des limites de débit plus élevées que Pro
- Groupez les requêtes — regroupez les prompts liés quand c'est possible
Étape 10 : Conseils pour la production
Configuration de l'environnement
// src/config.ts
interface GeminiConfig {
apiKey: string;
model: string;
maxRetries: number;
timeout: number;
}
export function getConfig(): GeminiConfig {
const apiKey = process.env.GEMINI_API_KEY;
if (!apiKey) {
throw new Error("La variable d'environnement GEMINI_API_KEY est requise");
}
return {
apiKey,
model: process.env.GEMINI_MODEL || "gemini-2.5-flash",
maxRetries: parseInt(process.env.GEMINI_MAX_RETRIES || "3", 10),
timeout: parseInt(process.env.GEMINI_TIMEOUT || "30000", 10),
};
}Comptage des tokens
Avant d'envoyer de longs prompts, vérifiez le nombre de tokens :
async function countTokens(content: string) {
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
const result = await model.countTokens(content);
console.log(`Nombre de tokens: ${result.totalTokens}`);
return result.totalTokens;
}Estimation des coûts
function estimateCost(
inputTokens: number,
outputTokens: number,
model: "pro" | "flash" | "flash-lite"
) {
// Prix approximatifs par million de tokens (vérifiez les prix actuels)
const pricing = {
pro: { input: 1.25, output: 10.0 },
flash: { input: 0.15, output: 0.6 },
"flash-lite": { input: 0.075, output: 0.3 },
};
const p = pricing[model];
const inputCost = (inputTokens / 1_000_000) * p.input;
const outputCost = (outputTokens / 1_000_000) * p.output;
return {
inputCost: `$${inputCost.toFixed(4)}`,
outputCost: `$${outputCost.toFixed(4)}`,
totalCost: `$${(inputCost + outputCost).toFixed(4)}`,
};
}Dépannage
Problèmes courants
"API key not valid" — Clé API invalide
- Vérifiez votre clé sur aistudio.google.com
- Assurez-vous que l'API Generative AI est activée dans votre projet Google Cloud
- Vérifiez que votre clé n'est pas restreinte à des API spécifiques
"Resource exhausted" — Erreurs 429
- Vous avez atteint la limite de débit. Implémentez un backoff exponentiel
- Envisagez de passer à un forfait payant pour des limites plus élevées
- Utilisez
gemini-2.5-flashqui a des limites de débit plus généreuses
"Content blocked by safety filters" — Contenu bloqué par les filtres de sécurité
- Ajustez les seuils de
safetySettings(mais soyez responsable) - Reformulez le prompt pour éviter de déclencher les filtres
- Consultez les politiques d'utilisation de Google
Réponses vides
- Le modèle a peut-être été bloqué par les filtres de sécurité sans retourner de texte
- Vérifiez
response.promptFeedbackpour les raisons du blocage
Prochaines étapes
Maintenant que vous maîtrisez les fondamentaux de Gemini API, explorez ces sujets avancés :
- Gemini avec LangChain.js — Construire des chaînes et des agents IA complexes
- Vertex AI — Déploiement de niveau entreprise avec Google Cloud
- Fine-tuning — Personnaliser les modèles Gemini pour votre domaine
- Mise en cache du contexte — Réduire les coûts pour les fenêtres de contexte répétées
- Ancrage avec Google Search — Enrichir les réponses avec des données web en temps réel
Conclusion
Vous avez construit une boîte à outils complète pour les applications IA avec Google Gemini API et TypeScript. De la simple génération de texte à l'analyse multimodale, le streaming, les appels de fonctions et les sorties structurées — vous disposez maintenant de tous les composants pour créer des applications IA sophistiquées.
La combinaison d'une fenêtre de contexte massive, de tarifs compétitifs et d'un support multimodal natif fait de Gemini API un excellent choix pour les applications IA en production. Commencez avec Flash pour la rapidité de développement, et passez à Pro quand vous avez besoin de capacités de raisonnement améliorées.
Discutez de votre projet avec nous
Nous sommes ici pour vous aider avec vos besoins en développement Web. Planifiez un appel pour discuter de votre projet et comment nous pouvons vous aider.
Trouvons les meilleures solutions pour vos besoins.
Articles connexes

Construire des agents IA from scratch avec TypeScript : maîtriser le pattern ReAct avec le Vercel AI SDK
Apprenez à construire des agents IA depuis zéro avec TypeScript. Ce tutoriel couvre le pattern ReAct, l'appel d'outils, le raisonnement multi-étapes et les boucles d'agents prêtes pour la production avec le Vercel AI SDK.

Construire votre premier serveur MCP avec TypeScript : Outils, Ressources et Prompts
Apprenez a construire un serveur MCP pret pour la production en partant de zero avec TypeScript. Ce tutoriel pratique couvre les outils, les ressources, les prompts, le transport stdio, et la connexion a Claude Desktop et Cursor.

Construire un Chatbot IA Local avec Ollama et Next.js : Guide Complet
Construisez un chatbot IA privé fonctionnant entièrement sur votre machine locale avec Ollama et Next.js. Ce tutoriel pratique couvre l'installation, le streaming des réponses, la sélection de modèles et le déploiement d'une interface de chat prête pour la production — le tout sans envoyer de données dans le cloud.