Introduction aux Chatbots IA

Les chatbots intelligents révolutionnent l'interaction homme-machine en offrant des conversations naturelles et contextuelles. Dans ce tutoriel, nous allons créer un chatbot complet utilisant Python, Streamlit et les dernières technologies NLP.

Prérequis

  • Python 3.8+ installé
  • Connaissances de base en Python
  • Compte OpenAI (pour GPT) ou Hugging Face
  • Éditeur de code (VS Code recommandé)

Architecture du Chatbot

Notre chatbot comprendra :

  • Interface utilisateur : Streamlit pour l'UI web
  • Moteur NLP : OpenAI GPT ou modèles Hugging Face
  • Mémoire conversationnelle : Historique des échanges
  • Base de connaissances : Documents et FAQ
  • Système de personnalité : Ton et style du bot

Étape 1 : Installation des Dépendances

# requirements.txt
streamlit==1.28.1
openai==1.3.5
langchain==0.0.340
chromadb==0.4.18
sentence-transformers==2.2.2
python-dotenv==1.0.0
pandas==2.1.3
numpy==1.24.3
# Installation
pip install -r requirements.txt

Étape 2 : Configuration de Base

# config.py
import os
from dotenv import load_dotenv

load_dotenv()

class Config:
    OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
    MODEL_NAME = "gpt-3.5-turbo"
    MAX_TOKENS = 150
    TEMPERATURE = 0.7
    
    # Personnalité du chatbot
    SYSTEM_PROMPT = """
    Tu es un assistant IA spécialisé en technologie et innovation.
    Tu es professionnel, bienveillant et toujours prêt à aider.
    Tu réponds en français et de manière concise mais complète.
    Si tu ne connais pas une réponse, tu l'admets honnêtement.
    """
    
    # Configuration Streamlit
    PAGE_TITLE = "ChatBot IA - Assistant Tech"
    PAGE_ICON = "🤖"

Étape 3 : Moteur de Conversation

# chatbot_engine.py
import openai
from typing import List, Dict
import json
from datetime import datetime

class ChatbotEngine:
    def __init__(self, api_key: str, model: str = "gpt-3.5-turbo"):
        openai.api_key = api_key
        self.model = model
        self.conversation_history = []
        self.system_prompt = Config.SYSTEM_PROMPT
        
    def add_message(self, role: str, content: str):
        """Ajouter un message à l'historique"""
        message = {
            "role": role,
            "content": content,
            "timestamp": datetime.now().isoformat()
        }
        self.conversation_history.append(message)
        
    def get_response(self, user_message: str) -> str:
        """Obtenir une réponse du chatbot"""
        try:
            # Ajouter le message utilisateur
            self.add_message("user", user_message)
            
            # Préparer les messages pour l'API
            messages = [{"role": "system", "content": self.system_prompt}]
            
            # Ajouter l'historique (limité aux 10 derniers échanges)
            recent_history = self.conversation_history[-20:]  # 10 échanges
            for msg in recent_history:
                messages.append({
                    "role": msg["role"],
                    "content": msg["content"]
                })
            
            # Appel à l'API OpenAI
            response = openai.ChatCompletion.create(
                model=self.model,
                messages=messages,
                max_tokens=Config.MAX_TOKENS,
                temperature=Config.TEMPERATURE
            )
            
            bot_response = response.choices[0].message.content.strip()
            
            # Ajouter la réponse à l'historique
            self.add_message("assistant", bot_response)
            
            return bot_response
            
        except Exception as e:
            return f"Désolé, une erreur s'est produite : {str(e)}"
    
    def clear_history(self):
        """Effacer l'historique de conversation"""
        self.conversation_history = []
        
    def export_conversation(self) -> str:
        """Exporter la conversation en JSON"""
        return json.dumps(self.conversation_history, indent=2, ensure_ascii=False)

Étape 4 : Base de Connaissances

# knowledge_base.py
import chromadb
from sentence_transformers import SentenceTransformer
import pandas as pd
from typing import List

class KnowledgeBase:
    def __init__(self):
        self.client = chromadb.Client()
        self.collection = self.client.create_collection("knowledge")
        self.encoder = SentenceTransformer('all-MiniLM-L6-v2')
        self.load_knowledge()
        
    def load_knowledge(self):
        """Charger la base de connaissances"""
        # Exemple de données de connaissances
        knowledge_data = [
            {
                "id": "1",
                "question": "Qu'est-ce que l'intelligence artificielle ?",
                "answer": "L'IA est une technologie qui permet aux machines de simuler l'intelligence humaine pour résoudre des problèmes complexes.",
                "category": "IA"
            },
            {
                "id": "2", 
                "question": "Comment fonctionne le machine learning ?",
                "answer": "Le ML utilise des algorithmes pour apprendre automatiquement à partir de données sans être explicitement programmé.",
                "category": "ML"
            },
            {
                "id": "3",
                "question": "Qu'est-ce que Python ?",
                "answer": "Python est un langage de programmation polyvalent, facile à apprendre et très utilisé en data science et IA.",
                "category": "Programmation"
            }
        ]
        
        # Ajouter à la collection
        for item in knowledge_data:
            embedding = self.encoder.encode(item["question"]).tolist()
            self.collection.add(
                embeddings=[embedding],
                documents=[item["answer"]],
                metadatas=[{"question": item["question"], "category": item["category"]}],
                ids=[item["id"]]
            )
    
    def search_knowledge(self, query: str, n_results: int = 3) -> List[Dict]:
        """Rechercher dans la base de connaissances"""
        query_embedding = self.encoder.encode(query).tolist()
        
        results = self.collection.query(
            query_embeddings=[query_embedding],
            n_results=n_results
        )
        
        knowledge_items = []
        for i in range(len(results['documents'][0])):
            knowledge_items.append({
                "question": results['metadatas'][0][i]['question'],
                "answer": results['documents'][0][i],
                "category": results['metadatas'][0][i]['category'],
                "distance": results['distances'][0][i]
            })
            
        return knowledge_items

Étape 5 : Interface Streamlit

# app.py
import streamlit as st
from chatbot_engine import ChatbotEngine
from knowledge_base import KnowledgeBase
from config import Config
import time

# Configuration de la page
st.set_page_config(
    page_title=Config.PAGE_TITLE,
    page_icon=Config.PAGE_ICON,
    layout="wide"
)

# Initialisation du session state
if "chatbot" not in st.session_state:
    st.session_state.chatbot = ChatbotEngine(Config.OPENAI_API_KEY)
    
if "knowledge_base" not in st.session_state:
    st.session_state.knowledge_base = KnowledgeBase()
    
if "messages" not in st.session_state:
    st.session_state.messages = []

# Interface utilisateur
def main():
    st.title("🤖 ChatBot IA - Assistant Tech")
    st.markdown("---")
    
    # Sidebar avec options
    with st.sidebar:
        st.header("⚙️ Options")
        
        # Bouton pour effacer l'historique
        if st.button("🗑️ Effacer l'historique"):
            st.session_state.messages = []
            st.session_state.chatbot.clear_history()
            st.success("Historique effacé!")
            
        # Paramètres avancés
        st.subheader("Paramètres")
        temperature = st.slider("Créativité", 0.0, 1.0, Config.TEMPERATURE)
        max_tokens = st.slider("Longueur réponse", 50, 300, Config.MAX_TOKENS)
        
        # Mode recherche dans la base de connaissances
        use_knowledge = st.checkbox("Utiliser la base de connaissances", True)
        
        # Statistiques
        st.subheader("📊 Statistiques")
        st.metric("Messages envoyés", len(st.session_state.messages))
        
    # Zone de chat principale
    chat_container = st.container()
    
    with chat_container:
        # Afficher l'historique des messages
        for message in st.session_state.messages:
            with st.chat_message(message["role"]):
                st.write(message["content"])
                if "timestamp" in message:
                    st.caption(f"🕒 {message['timestamp']}")
    
    # Zone de saisie
    if prompt := st.chat_input("Tapez votre message ici..."):
        # Ajouter le message utilisateur
        user_message = {
            "role": "user",
            "content": prompt,
            "timestamp": time.strftime("%H:%M:%S")
        }
        st.session_state.messages.append(user_message)
        
        # Afficher le message utilisateur
        with st.chat_message("user"):
            st.write(prompt)
            st.caption(f"🕒 {user_message['timestamp']}")
        
        # Recherche dans la base de connaissances
        relevant_knowledge = ""
        if use_knowledge:
            knowledge_results = st.session_state.knowledge_base.search_knowledge(prompt)
            if knowledge_results and knowledge_results[0]["distance"] < 0.7:
                relevant_knowledge = f"\n\nInformation pertinente : {knowledge_results[0]['answer']}"
        
        # Obtenir la réponse du chatbot
        with st.chat_message("assistant"):
            with st.spinner("🤔 Réflexion en cours..."):
                enhanced_prompt = prompt + relevant_knowledge
                response = st.session_state.chatbot.get_response(enhanced_prompt)
                
                st.write(response)
                
                # Ajouter la réponse à l'historique
                bot_message = {
                    "role": "assistant",
                    "content": response,
                    "timestamp": time.strftime("%H:%M:%S")
                }
                st.session_state.messages.append(bot_message)
                st.caption(f"🕒 {bot_message['timestamp']}")

if __name__ == "__main__":
    main()

Étape 6 : Fonctionnalités Avancées

Système de Personnalités

# personalities.py
class PersonalityManager:
    PERSONALITIES = {
        "professionnel": {
            "name": "Assistant Professionnel",
            "prompt": "Tu es un assistant professionnel, formel et précis.",
            "emoji": "👔"
        },
        "amical": {
            "name": "Assistant Amical", 
            "prompt": "Tu es un assistant amical, décontracté et encourageant.",
            "emoji": "😊"
        },
        "expert": {
            "name": "Expert Technique",
            "prompt": "Tu es un expert technique qui donne des réponses détaillées et précises.",
            "emoji": "🔬"
        }
    }
    
    @classmethod
    def get_personality(cls, personality_key: str) -> dict:
        return cls.PERSONALITIES.get(personality_key, cls.PERSONALITIES["professionnel"])

Analyse de Sentiment

# sentiment_analyzer.py
from transformers import pipeline

class SentimentAnalyzer:
    def __init__(self):
        self.analyzer = pipeline("sentiment-analysis", 
                               model="nlptown/bert-base-multilingual-uncased-sentiment")
    
    def analyze(self, text: str) -> dict:
        result = self.analyzer(text)[0]
        return {
            "sentiment": result["label"],
            "confidence": result["score"]
        }

Export de Conversations

# export_utils.py
import json
import csv
from datetime import datetime

def export_to_json(messages: list) -> str:
    """Exporter en JSON"""
    export_data = {
        "export_date": datetime.now().isoformat(),
        "total_messages": len(messages),
        "conversation": messages
    }
    return json.dumps(export_data, indent=2, ensure_ascii=False)

def export_to_csv(messages: list) -> str:
    """Exporter en CSV"""
    import io
    output = io.StringIO()
    writer = csv.writer(output)
    writer.writerow(["Role", "Content", "Timestamp"])
    
    for msg in messages:
        writer.writerow([
            msg["role"],
            msg["content"],
            msg.get("timestamp", "")
        ])
    
    return output.getvalue()

Étape 7 : Tests et Validation

# test_chatbot.py
import unittest
from chatbot_engine import ChatbotEngine
from knowledge_base import KnowledgeBase

class TestChatbot(unittest.TestCase):
    def setUp(self):
        self.chatbot = ChatbotEngine("test-key")
        self.kb = KnowledgeBase()
    
    def test_message_history(self):
        self.chatbot.add_message("user", "Test message")
        self.assertEqual(len(self.chatbot.conversation_history), 1)
    
    def test_knowledge_search(self):
        results = self.kb.search_knowledge("intelligence artificielle")
        self.assertGreater(len(results), 0)
    
    def test_clear_history(self):
        self.chatbot.add_message("user", "Test")
        self.chatbot.clear_history()
        self.assertEqual(len(self.chatbot.conversation_history), 0)

if __name__ == "__main__":
    unittest.main()

Étape 8 : Déploiement

Fichier de Configuration Docker

# Dockerfile
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

EXPOSE 8501

CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]

Déploiement sur Streamlit Cloud

  1. Pusher le code sur GitHub
  2. Connecter le repo à Streamlit Cloud
  3. Configurer les variables d'environnement
  4. Déployer automatiquement

Fonctionnalités Bonus

Reconnaissance Vocale

# voice_recognition.py
import speech_recognition as sr
import pyttsx3

class VoiceInterface:
    def __init__(self):
        self.recognizer = sr.Recognizer()
        self.tts = pyttsx3.init()
        
    def listen(self) -> str:
        with sr.Microphone() as source:
            audio = self.recognizer.listen(source)
            try:
                return self.recognizer.recognize_google(audio, language='fr-FR')
            except:
                return ""
    
    def speak(self, text: str):
        self.tts.say(text)
        self.tts.runAndWait()

Intégration API

# api_integration.py
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class ChatRequest(BaseModel):
    message: str
    user_id: str

class ChatResponse(BaseModel):
    response: str
    timestamp: str

@app.post("/chat", response_model=ChatResponse)
async def chat_endpoint(request: ChatRequest):
    # Logique du chatbot
    response = chatbot.get_response(request.message)
    
    return ChatResponse(
        response=response,
        timestamp=datetime.now().isoformat()
    )

Optimisations et Bonnes Pratiques

Gestion d'Erreurs

  • Try-catch : Gestion des erreurs API
  • Fallback responses : Réponses de secours
  • Rate limiting : Limitation des requêtes
  • Logging : Traçabilité des erreurs

Performance

  • Cache : Mise en cache des réponses fréquentes
  • Async : Traitement asynchrone
  • Batch processing : Traitement par lots
  • Model optimization : Modèles légers

Sécurité

  • Variables d'environnement : Clés API sécurisées
  • Input validation : Validation des entrées
  • Rate limiting : Protection contre le spam
  • Content filtering : Filtrage de contenu

Lancement de l'Application

# Commande pour lancer
streamlit run app.py

# Avec configuration personnalisée
streamlit run app.py --server.port 8080 --server.address 0.0.0.0

Conclusion

Félicitations ! Vous avez créé un chatbot IA complet avec :

  • Interface utilisateur moderne avec Streamlit
  • Intégration GPT pour des réponses intelligentes
  • Base de connaissances avec recherche sémantique
  • Historique de conversation persistant
  • Fonctionnalités avancées (export, personnalités)

Ce chatbot peut être étendu avec de nombreuses fonctionnalités : reconnaissance vocale, intégration API, analyse de sentiment, et bien plus encore.

Besoin d'aide pour développer votre chatbot personnalisé ? Contactez-moi pour un accompagnement sur mesure.