Comprendre l'intelligence artificielle en l'utilisant. Du chat au RAG, avec du code. Sans maths, accessible a tous.
L'intelligence artificielle, c'est quoi au juste ?
Imagine que tu veux apprendre a un enfant a reconnaitre des fruits. Tu lui montres 1000 pommes, 1000 oranges, 1000 bananes. Au debut, il se trompe. Tu corriges. Petit a petit, il apprend les motifs : la pomme est ronde et rouge, l'orange est orange et pele, la banane est longue et jaune.
L'IA fait exactement la meme chose. Sauf qu'au lieu d'un enfant, c'est un programme informatique. Et au lieu de "voir" des fruits, il "voit" des nombres.
Ces trois termes sont souvent utilises de maniere interchangeable, mais ils s'emboitent :
┌─────────────────────────────────────────────────────────────┐ │ INTELLIGENCE ARTIFICIELLE │ │ Tout programme qui simule une intelligence humaine │ │ (chatbot, pathfinding jeu video, recommandation) │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ MACHINE LEARNING │ │ │ │ Programmes qui apprennent a partir de donnees │ │ │ │ (regression, arbres de decision, spam filter) │ │ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ │ │ DEEP LEARNING │ │ │ │ │ │ Reseaux de neurones profonds │ │ │ │ │ │ ChatGPT, Claude, reconnaissance d'images │ │ │ │ │ └───────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘
Avant de manipuler l'IA, voici le vocabulaire de base. Pas de jargon, juste les mots qu'on croise partout.
| Mot | En clair | Exemple |
|---|---|---|
| Modele | Un programme entraine sur des donnees, pret a l'emploi | llama3.2, GPT-4, Claude |
| Token | Un morceau de mot (pas un mot entier). L'IA decoupe le texte en tokens | "Bonjour" = 1 token, "anticonstitutionnellement" = plusieurs tokens |
| Contexte | La quantite de texte que le modele "voit" en une fois | Un contexte de 8k tokens = environ 6000 mots |
| Prompt | La question ou l'instruction qu'on donne au modele | "Resume ce texte en 3 points" |
| Temperature | Le niveau d'aleatoire. 0 = deterministe, 1 = creatif | 0 pour du code, 0.7 pour un texte creatif |
| Hallucination | Quand le modele invente un fait plausible mais faux | "Selon Wikipedia, Napoleon est ne en 1985..." |
| Fine-tuning | Ré-entrainer un modele sur tes propres donnees pour le specialiser | Un modele qui parle comme toi, sur ton style |
| Embeddings | Une representation numerique du "sens" d'un texte | Voir section 5 |
| RAG | Retrieval Augmented Generation : donner ses docs a l'IA avant de poser une question | "Dans mes notes PDF, quelle est la recette de la tarte ?" |
Tous les modeles ne font pas la meme chose. Voici les grandes familles :
| Famille | Ce qu'elle fait | Exemples | Usage type |
|---|---|---|---|
| LLM (texte) | Genere et comprend du texte | llama3.2, phi3, mistral, GPT-4, Claude | Chat, resume, traduction, code |
| Embeddings | Transforme du texte en vecteurs numeriques | nomic-embed-text, all-minilm | Recherche semantique, RAG |
| Images | Genere ou decrit des images | stable-diffusion, llava, midjourney | Creation visuelle, description d'image |
| Audio | Transcrit ou genere de la parole | whisper, piper | Transcription, synthese vocale |
Pour ce tuto, on va se concentrer sur les LLM et les embeddings, parce que c'est ce qui couvre 90% des usages perso.
On commence par le plus simple : installer un modele en local et lui parler.
Ollama est un outil qui lance des modeles d'IA en local, gratuitement, sans compte.
# Linux / macOS
curl -fsSL https://ollama.com/install.sh | sh
# Windows : telecharger https://ollama.com/download
# Verifier l'installation
ollama --version
Ollama telecharge et lance un modele en une seule commande. On commence avec un petit modele rapide :
# Lancer llama3.2 (3 milliards de parametres, ~2 Go)
ollama run llama3.2
# Autres modeles interessants pour debuter :
# ollama run phi3 # Tres petit, tres rapide
# ollama run mistral # Bon generaliste
# ollama run llama3.2:1b # Ultra leger pour tests
La premiere fois, Ollama telecharge le modele (2 Go pour llama3.2, quelques minutes). Ensuite, tu te retrouves dans un chat direct dans le terminal :
$ ollama run llama3.2 >>> Bonjour, tu peux te presenter ? Bonjour ! Je suis Llama 3.2, un modele de langage entraine par Meta... >>> Resume-moi ce texte en 3 points : >>> L'intelligence artificielle est un domaine de l'informatique... 1. L'IA simule l'intelligence humaine 2. Elle apprend a partir de donnees 3. Elle ne "comprend" pas, elle predit
Un prompt, c'est l'instruction que tu donnes au modele. La qualite de la reponse depend directement de la qualite du prompt. Quelques exemples concrets :
# Traduction
>>> Traduis en anglais : "Le chat dort sur le canape"
"The cat is sleeping on the couch"
# Brainstorm
>>> Donne-moi 5 idees de noms pour un site de streaming
1. CineSphere
2. StreamHub
3. ...
# Code
>>> Ecris une fonction JavaScript qui verifie si un nombre est premier
function isPrime(n) { ... }
# Role
>>> Tu es un professeur de maths. Explique-moi les fractions
comme si j'avais 10 ans.
Ollama expose une API HTTP sur le port 11434. Tu peux l'appeler depuis n'importe quel langage :
// Appeler un modele Ollama en JavaScript
const OLLAMA_URL = 'http://localhost:11434';
const MODEL = 'llama3.2';
async function chat(prompt) {
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: MODEL,
prompt: prompt,
stream: false
})
});
const data = await response.json();
return data.response;
}
// Test
const reponse = await chat('Resume en 1 phrase : l\'IA est un outil statistique.');
console.log(reponse);
# Appeler un modele Ollama en Python
import requests
OLLAMA_URL = 'http://localhost:11434'
MODEL = 'llama3.2'
def chat(prompt):
response = requests.post(f'{OLLAMA_URL}/api/generate', json={
'model': MODEL,
'prompt': prompt,
'stream': False
})
return response.json()['response']
# Test
reponse = chat("Resume en 1 phrase : l'IA est un outil statistique.")
print(reponse)
Jusqu'ici, on a parle a un modele "vide" : il ne connait que ce qu'il a appris pendant son entrainement. Mais si tu veux qu'il reponde a partir de tes documents (tes PDF, tes notes, ta doc) ? C'est la qu'interviennent les embeddings et le RAG.
Un embedding, c'est une representation numerique du "sens" d'un texte. On donne une phrase a un modele, il renvoie un vecteur de nombres (souvent 768 ou 1024 nombres). Deux phrases qui veulent dire la meme chose auront des vecteurs proches.
TEXTE EMBEDDING (vecteur de nombres) "Le chat dort" ──▶ [0.12, -0.34, 0.56, 0.23, ...] "Le chat fait une" ──▶ [0.11, -0.32, 0.55, 0.22, ...] ← tres similaire "sieste" "La voiture roule" ──▶ [-0.45, 0.23, 0.12, -0.67, ...] ← different
On peut comparer deux embeddings avec une similarite cosinus : plus le resultat est proche de 1, plus les textes sont proches en sens. Pas besoin de comprendre la formule, juste le principe : plus c'est proche de 1, plus ca veut dire la meme chose.
RAG = Retrieval Augmented Generation. En clair :
MES DOCUMENTS QUESTION
│ │
▼ ▼
[Embeddings] [Embedding de la question]
│ │
└─────────┬──────────────────┘
▼
[Morceaux les plus proches]
│
▼
┌─────────────────────┐
│ LLM + contexte │ ──▶ Reponse basee sur MES docs
│ "Voici mes notes, │
│ reponds a la │
│ question" │
└─────────────────────┘
C'est exactement comme ca que fonctionne ChatGPT quand tu lui donnes un fichier : il ne "lit" pas ton fichier a chaque message, il cherche les parties pertinentes et les donne au modele.
On va poser des questions sur le contenu d'un PDF. Pour rester simple, on prend un PDF texte (pas un scan). Le principe :
D'abord, installe le modele d'embeddings :
ollama pull nomic-embed-text
Ensuite, le code complet :
// RAG sur un PDF en JavaScript
// Dependances : npm install pdf-parse
import fs from 'node:fs/promises';
const OLLAMA_URL = 'http://localhost:11434';
const EMBED_MODEL = 'nomic-embed-text';
const LLM_MODEL = 'llama3.2';
// 1. Lire et decouper un PDF en morceaux
import pdf from 'pdf-parse';
const buffer = await fs.readFile('mon-document.pdf');
const data = await pdf(buffer);
const text = data.text;
// Decoupage simple : morceaux de 500 caracteres
function chunk(text, size = 500) {
const chunks = [];
for (let i = 0; i < text.length; i += size) {
chunks.push(text.slice(i, i + size));
}
return chunks;
}
const chunks = chunk(text);
console.log(`${chunks.length} morceaux extraits`);
// 2. Calculer l'embedding de chaque morceau
async function getEmbedding(text) {
const response = await fetch(`${OLLAMA_URL}/api/embeddings`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model: EMBED_MODEL, prompt: text })
});
return (await response.json()).embedding;
}
const embeddings = [];
for (const c of chunks) {
embeddings.push(await getEmbedding(c));
}
// 3. Similarite cosinus
function cosine(a, b) {
let dot = 0, na = 0, nb = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
na += a[i] * a[i];
nb += b[i] * b[i];
}
return dot / (Math.sqrt(na) * Math.sqrt(nb));
}
// 4. Poser une question
async function ask(question) {
const qEmb = await getEmbedding(question);
// Trouver les 3 morceaux les plus proches
const scores = embeddings.map((emb, i) => ({
text: chunks[i],
score: cosine(qEmb, emb)
})).sort((a, b) => b.score - a.score).slice(0, 3);
const context = scores.map(s => s.text).join('\n\n');
// Donner le contexte au LLM
const prompt = `Reponds a la question en te basant sur ce contexte. Si la reponse n'est pas dans le contexte, dis-le.
Contexte :
${context}
Question : ${question}`;
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model: LLM_MODEL, prompt, stream: false })
});
return (await response.json()).response;
}
// Test
const reponse = await ask('Quelle est l'idee principale du document ?');
console.log(reponse);
# RAG sur un PDF en Python
# Dependances : pip install pymupdf requests
import requests
import fitz # pymupdf
OLLAMA_URL = 'http://localhost:11434'
EMBED_MODEL = 'nomic-embed-text'
LLM_MODEL = 'llama3.2'
# 1. Lire et decouper un PDF
doc = fitz.open('mon-document.pdf')
text = ''.join(page.get_text() for page in doc)
def chunk(text, size=500):
return [text[i:i+size] for i in range(0, len(text), size)]
chunks = chunk(text)
print(f'{len(chunks)} morceaux extraits')
# 2. Embeddings
def get_embedding(text):
response = requests.post(f'{OLLAMA_URL}/api/embeddings', json={
'model': EMBED_MODEL, 'prompt': text
})
return response.json()['embedding']
embeddings = [get_embedding(c) for c in chunks]
# 3. Similarite cosinus
def cosine(a, b):
dot = sum(x*y for x, y in zip(a, b))
na = sum(x**2 for x in a) ** 0.5
nb = sum(x**2 for x in b) ** 0.5
return dot / (na * nb)
# 4. Poser une question
def ask(question):
q_emb = get_embedding(question)
scores = sorted(
[{'text': chunks[i], 'score': cosine(q_emb, embeddings[i])}
for i in range(len(chunks))],
key=lambda x: x['score'], reverse=True
)[:3]
context = '\n\n'.join(s['text'] for s in scores)
prompt = f"""Reponds a la question en te basant sur ce contexte. Si la reponse n'est pas dans le contexte, dis-le.
Contexte :
{context}
Question : {question}"""
response = requests.post(f'{OLLAMA_URL}/api/generate', json={
'model': LLM_MODEL, 'prompt': prompt, 'stream': False
})
return response.json()['response']
# Test
reponse = ask("Quelle est l'idee principale du document ?")
print(reponse)
Maintenant qu'on sait appeler un modele, on peut le servir en HTTP pour que d'autres apps s'y connectent. On construit une mini-API avec deux endpoints : /chat et /embed.
// api-ia.js - Mini API IA avec Express
// npm install express
import express from 'express';
const app = express();
app.use(express.json());
const OLLAMA_URL = 'http://localhost:11434';
// POST /chat { "prompt": "..." }
app.post('/chat', async (req, res) => {
try {
const response = await fetch(`${OLLAMA_URL}/api/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'llama3.2',
prompt: req.body.prompt,
stream: false
})
});
const data = await response.json();
res.json({ reponse: data.response });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
// POST /embed { "text": "..." }
app.post('/embed', async (req, res) => {
try {
const response = await fetch(`${OLLAMA_URL}/api/embeddings`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'nomic-embed-text',
prompt: req.body.text
})
});
const data = await response.json();
res.json({ embedding: data.embedding });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
// Healthcheck
app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.listen(3000, () => console.log('API IA sur http://localhost:3000'));
# api_ia.py - Mini API IA avec Flask
# pip install flask requests
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
OLLAMA_URL = 'http://localhost:11434'
# POST /chat
@app.post('/chat')
def chat():
prompt = request.json.get('prompt', '')
response = requests.post(f'{OLLAMA_URL}/api/generate', json={
'model': 'llama3.2',
'prompt': prompt,
'stream': False
})
return jsonify({'reponse': response.json()['response']})
# POST /embed
@app.post('/embed')
def embed():
text = request.json.get('text', '')
response = requests.post(f'{OLLAMA_URL}/api/embeddings', json={
'model': 'nomic-embed-text',
'prompt': text
})
return jsonify({'embedding': response.json()['embedding']})
# Healthcheck
@app.get('/health')
def health():
return jsonify({'status': 'ok'})
if __name__ == '__main__':
app.run(port=3000)
On la lance en arriere-plan, on la teste :
# Lancer
node api-ia.js # ou python api_ia.py
# Tester
curl -X POST http://localhost:3000/chat \
-H "Content-Type: application/json" \
-d '{"prompt": "Bonjour, qui es-tu ?"}'
L'IA n'est pas magique. Voici les pieges qu'il faut connaitre avant de l'utiliser serieusement.
Un LLM predit le mot suivant. Il n'a aucun mecanisme pour dire "je ne sais pas". Si on lui demande un fait qu'il ne connait pas, il invente un truc plausible. C'est ce qu'on appelle une hallucination.
Comment mitiger :
Un modele apprend sur des donnees humaines. Les donnees humaines ont des biais (genre, origine, culture). Le modele peut reproduire ces biais dans ses reponses.
| Approche | Cout | Vitesse | Confidentialite |
|---|---|---|---|
| Ollama local (petit modele) | Gratuit | Depend de ta machine | Tout reste chez toi |
| API commerciale (OpenAI, Anthropic) | Payant au token | Tres rapide | Donnees envoyees au provider |
| Gros modele local (70B+) | Gratuit mais GPU requis | Lent sans bon hardware | Tout reste chez toi |
Si tu envoies des donnees sensibles a une API commerciale (OpenAI, Anthropic, Google), ces donnees transitent par leurs serveurs. Pour des documents prives, preferer un modele local (Ollama) ou un provider qui ne stocke pas les donnees.
ollama run llama3.2 — Generaliste equilibre, bon pour debuterollama run phi3 — Tres petit, tres rapide, suffisant pour beaucoup de tachesollama run mistral — Bon generaliste francophoneollama run qwen2.5 — Excellent en codeollama run llava — Decode et decrit des imagesollama pull nomic-embed-text — Modele d'embeddings pour le RAG