Tous les guides
IntermédiaireÀ votre rythmeGuide gratuitSection 84/95

Développer le backend et l'API

Pratiquez les fondations du développement : programmation, web, API, données et usages de l’IA. Des sections et exercices pour construire vos premiers projets.

💡

Contenu gratuit, accessible sans compte. Les outils et modèles évoluent : consultez le dossier actuel pour vérifier leurs versions. Modèles et sources

Section 11.5.6 : Développer le backend et l'API

🎯 Objectif pédagogique

Structurer le backend de l'application IA : modulariser le code, créer une couche API propre, gérer la configuration et les erreurs. Vous serez capable d'organiser le code backend d'un projet IA de manière professionnelle.


Du script au backend structuré

Marc a du code qui fonctionne. Mais tout est mélangé. Un backend professionnel est modulaire : chaque fichier a une responsabilité claire, les données circulent proprement, et les erreurs sont gérées.

Loading diagram…

config.py — Le cerveau de la configuration

# config.py — Configuration centralisée

import os
from dotenv import load_dotenv

load_dotenv()

# API Keys
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY")

# Modèles
DEFAULT_MODEL = "gpt-4o-mini"
PREMIUM_MODEL = "gpt-4o"
EMBEDDING_MODEL = "text-embedding-3-small"

# Limites
MAX_INPUT_LENGTH = 5000
MAX_HISTORY_MESSAGES = 20
SUMMARY_THRESHOLD = 15
MAX_TOKENS_RESPONSE = 1000

# ChromaDB
CHROMA_DB_PATH = "./data/chroma_db"
KNOWLEDGE_COLLECTION = "career_knowledge"

# System Prompt
SYSTEM_PROMPT = """Tu es CareerBot Pro, un assistant expert en reconversion tech/data/IA.

## Personnalité
- Ton : professionnel, chaleureux, encourageant
- Tu tutoies l'utilisateur
- Direct, concret, orienté action

## Compétences
- Analyse de profils et offres d'emploi
- Conseil en formation et montée en compétences
- Préparation aux entretiens
- Données marché (salaires, tendances)

## Règles
- Base tes réponses sur la base de connaissances quand disponible
- Cite tes sources quand tu utilises la base
- Limite tes réponses à 300 mots max
- Termine par une question ou suggestion d'action
- NE JAMAIS inventer d'offres d'emploi
- NE JAMAIS donner de conseil juridique ou médical
"""

# App Config
APP_CONFIG = \{
    "title": "CareerBot Pro — Assistant Reconversion Tech",
    "icon": "🤖",
    "theme_color": "#0891B2",
\}

knowledge.py — Gestion de la base de connaissances

# knowledge.py — Indexation et recherche

import chromadb
from config import CHROMA_DB_PATH, KNOWLEDGE_COLLECTION
from pathlib import Path

class KnowledgeBase:
    """Gestion de la base de connaissances vectorielle."""
    
    def __init__(self):
        self.client = chromadb.PersistentClient(path=CHROMA_DB_PATH)
        self.collection = self.client.get_or_create_collection(
            name=KNOWLEDGE_COLLECTION,
            metadata=\{"hnsw:space": "cosine"\}
        )
    
    def index_directory(self, directory="data/knowledge"):
        """Indexer tous les fichiers .txt d'un dossier."""
        knowledge_dir = Path(directory)
        if not knowledge_dir.exists():
            print(f"Dossier \{directory\} non trouvé.")
            return
        
        all_chunks = []
        all_ids = []
        all_metadatas = []
        
        for filepath in knowledge_dir.glob("*.txt"):
            content = filepath.read_text(encoding="utf-8")
            chunks = self._chunk_text(content)
            
            for i, chunk in enumerate(chunks):
                all_chunks.append(chunk)
                all_ids.append(f"\{filepath.stem\}_chunk_\{i\}")
                all_metadatas.append(\{
                    "source": filepath.stem,
                    "chunk_index": i
                \})
        
        if all_chunks:
            self.collection.upsert(
                documents=all_chunks,
                ids=all_ids,
                metadatas=all_metadatas
            )
            print(f"Indexé \{len(all_chunks)\} chunks depuis \{len(list(knowledge_dir.glob('*.txt')))\} fichiers.")
    
    def search(self, query, n_results=3):
        """Recherche sémantique."""
        results = self.collection.query(
            query_texts=[query],
            n_results=n_results
        )
        
        return [
            \{"text": doc, "source": meta["source"]\}
            for doc, meta in zip(results["documents"][0], results["metadatas"][0])
        ]
    
    def _chunk_text(self, text, chunk_size=500, overlap=50):
        """Découper un texte en chunks."""
        words = text.split()
        chunks = []
        for i in range(0, len(words), chunk_size - overlap):
            chunk = " ".join(words[i:i + chunk_size])
            if chunk.strip():
                chunks.append(chunk)
        return chunks
    
    def get_stats(self):
        """Statistiques de la base."""
        return \{
            "total_documents": self.collection.count(),
            "collection_name": KNOWLEDGE_COLLECTION
        \}

tools.py — Définition des outils de l'agent

# tools.py — Fonctions et définitions OpenAI

import json
from knowledge import KnowledgeBase
from openai import OpenAI
from config import OPENAI_API_KEY, DEFAULT_MODEL

client = OpenAI(api_key=OPENAI_API_KEY)
kb = KnowledgeBase()

# Définitions OpenAI format
TOOL_DEFINITIONS = [
    \{
        "type": "function",
        "function": \{
            "name": "search_knowledge",
            "description": "Recherche dans la base de connaissances carrière.",
            "parameters": \{
                "type": "object",
                "properties": \{
                    "query": \{"type": "string", "description": "Question à rechercher"\}
                \},
                "required": ["query"]
            \}
        \}
    \},
    \{
        "type": "function",
        "function": \{
            "name": "analyze_profile",
            "description": "Analyse la compatibilité d'un profil avec un poste.",
            "parameters": \{
                "type": "object",
                "properties": \{
                    "profile": \{"type": "string"\},
                    "target_role": \{"type": "string"\}
                \},
                "required": ["profile", "target_role"]
            \}
        \}
    \},
    \{
        "type": "function",
        "function": \{
            "name": "create_action_plan",
            "description": "Crée un plan d'action personnalisé.",
            "parameters": \{
                "type": "object",
                "properties": \{
                    "goal": \{"type": "string"\},
                    "timeline": \{"type": "string"\}
                \},
                "required": ["goal"]
            \}
        \}
    \}
]

# Implémentations
def search_knowledge(query):
    chunks = kb.search(query, n_results=3)
    if not chunks:
        return "Aucune information trouvée dans la base."
    return "\n".join([f"[\{c['source']\}] \{c['text']\}" for c in chunks])

def analyze_profile(profile, target_role):
    context = search_knowledge(f"compétences \{target_role\}")
    response = client.chat.completions.create(
        model=DEFAULT_MODEL,
        messages=[\{
            "role": "user",
            "content": f"Analyse profil vs poste :\nProfil: \{profile\}\nPoste: \{target_role\}\nContexte: \{context\}\nScore 1-10, Forces, Gaps, Actions."
        \}],
        max_tokens=500
    )
    return response.choices[0].message.content

def create_action_plan(goal, timeline="3 mois"):
    context = search_knowledge(f"formation \{goal\}")
    response = client.chat.completions.create(
        model=DEFAULT_MODEL,
        messages=[\{
            "role": "user",
            "content": f"Plan d'action :\nObjectif: \{goal\}\nDurée: \{timeline\}\nContexte: \{context\}\nFormat: semaine par semaine, actions concrètes."
        \}],
        max_tokens=800
    )
    return response.choices[0].message.content

# Mapping
TOOL_MAP = \{
    "search_knowledge": search_knowledge,
    "analyze_profile": analyze_profile,
    "create_action_plan": create_action_plan,
\}

Convention de noms

Chaque fichier = une responsabilité. config.py ne fait que de la configuration. knowledge.py ne fait que du RAG. tools.py ne fait que des tools. Quand un bug survient, vous savez IMMÉDIATEMENT dans quel fichier chercher.

🏋️ Exercice pratique (30 minutes)

  1. →Créez les 3 fichiers : config.py, knowledge.py, tools.py
  2. →Testez knowledge.py en isolation (indexer 5 docs, chercher)
  3. →Testez tools.py en isolation (appeler chaque outil)
  4. →Vérifiez que les imports fonctionnent entre modules
Vérification rapide

Pourquoi séparer config.py des autres fichiers plutôt que mettre les constantes directement dans chaque fichier ?

Votre progression

Cette progression est déclarative et conservée dans votre navigateur. L’attestation finale ne constitue pas un diplôme ni une évaluation indépendante.

Voir ma progression et mon attestation

Apprendre l’IA, du premier prompt aux agents

15 guides gratuitsQuiz, schémas et ateliersSans compte

Un cas pratique IA dans votre boîte mail

Méthodes, ressources et nouveaux exercices. Gratuit, avec désinscription à tout moment.