ITSkillsCenter
Intelligence Artificielle

Premiers pas avec l’API DeepSeek en Python

13 min de lecture

Votre équipe support reçoit chaque jour les mêmes questions : « comment réinitialiser mon mot de passe VPN ? », « le serveur d’impression ne répond plus », « où trouver la procédure d’onboarding ? ». Répondre à la main coûte du temps. Dans ce guide, vous allez brancher un assistant capable de répondre à ces questions en langage naturel, en appelant l’API de DeepSeek depuis Python. À la fin, vous aurez une fonction demander_support() qui prend une question et renvoie une réponse claire, avec un coût mesuré à la fraction de centime près.

📍 Guide principal de la série : DeepSeek : modèles, API et déploiement local. Pour la vue d’ensemble (quel modèle choisir, cloud ou local, tarifs), lisez-le d’abord.

🎯 Ce que vous allez apprendre

  • Obtenir une clé API DeepSeek et la stocker sans la coder en dur dans vos fichiers.
  • Émettre un premier appel de complétion de chat et lire la réponse en Python.
  • Afficher la réponse au fil de l’eau (streaming) pour une expérience fluide.
  • Conduire une conversation à plusieurs tours en gardant le contexte.
  • Mesurer et réduire le coût grâce au cache de contexte intégré.
  • Rendre l’appel robuste : délais d’attente, erreurs réseau, nouvelles tentatives.

🛠️ Ce que vous allez construire

Un petit module Python assistant_support.py qui expose une fonction demander_support(question). Cette fonction envoie la question à DeepSeek avec une consigne système qui cadre le rôle (« tu es l’assistant interne du service informatique »), récupère la réponse, et journalise le nombre de jetons consommés. C’est la première brique d’un véritable assistant interne, que les guides suivants enrichiront avec le raisonnement structuré et le déploiement local.

Prérequis

  • Python 3.9 ou plus récent installé (python --version pour vérifier).
  • Un compte sur la plateforme DeepSeek avec un solde de crédit (l’API est payante à l’usage, mais les tarifs sont parmi les plus bas du marché — on y revient).
  • Connaître les bases de Python : fonctions, dictionnaires, gestion d’exceptions. Test express : si vous savez écrire une fonction qui lit une variable d’environnement, vous êtes prêt.
  • ⏱️ Temps estimé : environ 35 minutes.

Étape 1 — Obtenir une clé API et installer le SDK

L’API de DeepSeek est compatible avec le format d’OpenAI. Concrètement, cela signifie que vous n’avez pas besoin d’un client maison : la bibliothèque officielle openai fonctionne telle quelle, il suffit de la faire pointer vers les serveurs de DeepSeek. C’est un choix de conception délibéré qui vous laisse réutiliser tout l’écosystème existant.

Commencez par créer une clé depuis votre espace sur platform.deepseek.com (section API Keys), puis créditez un petit montant sur votre solde. Installez ensuite le SDK dans un environnement virtuel pour ne pas polluer votre système :

python -m venv .venv
source .venv/bin/activate    # sous Windows : .venv\Scripts\activate
pip install openai

La commande crée un environnement isolé, l’active, puis installe la bibliothèque. Si pip install se termine par une ligne du type Successfully installed openai-..., l’installation a réussi. Ne saisissez jamais votre clé directement dans le code : on va la lire depuis une variable d’environnement, ce qui évite de la pousser par accident sur un dépôt Git.

export DEEPSEEK_API_KEY="votre_cle_ici"   # à mettre dans ~/.bashrc ou ~/.zshrc

Sous Windows PowerShell, l’équivalent est $env:DEEPSEEK_API_KEY="votre_cle_ici". Pour un projet sérieux, préférez un fichier .env chargé par python-dotenv et ajouté à votre .gitignore.

Étape 2 — Le premier appel de complétion

Le cœur de l’API est l’endpoint chat completions : vous envoyez une liste de messages, le modèle renvoie un message d’assistant. Voici le squelette minimal. Notez le paramètre base_url qui redirige le client OpenAI vers DeepSeek — c’est la seule différence avec un appel OpenAI classique.

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["DEEPSEEK_API_KEY"],
    base_url="https://api.deepseek.com",
)

reponse = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[
        {"role": "system", "content": "Tu es l'assistant interne du service informatique. Reponds de facon concise et actionnable."},
        {"role": "user", "content": "Comment reinitialiser mon mot de passe VPN ?"},
    ],
    stream=False,
)

print(reponse.choices[0].message.content)

Le modèle deepseek-v4-flash est la variante rapide et économique de DeepSeek-V4 : c’est le bon choix par défaut pour un assistant de support, où la vitesse de réponse compte plus que le raisonnement profond. Pour les tâches exigeant une réflexion poussée, il existe deepseek-v4-pro, plus capable mais plus cher. À noter : sur les modèles V4, un mode de raisonnement est actif par défaut ; pour un assistant de support où la rapidité prime, on le désactive explicitement avec extra_body, comme dans la fonction de production de l’étape 7. En exécutant ce script, vous devez voir s’afficher une procédure de réinitialisation rédigée par le modèle. Si vous obtenez une erreur d’authentification, c’est que la variable d’environnement n’est pas lue : vérifiez qu’elle est bien exportée dans le terminal courant.

Point d’étape — À ce stade, un appel direct fonctionne et renvoie du texte. Pour vérifier : la sortie console contient une réponse cohérente, et votre solde sur la plateforme a baissé de quelques fractions de centime. Si rien ne s’affiche, ajoutez print(reponse) pour inspecter l’objet complet.

Étape 3 — Afficher la réponse en streaming

Attendre que toute la réponse soit générée avant de l’afficher donne une impression de lenteur, surtout pour les réponses longues. Le streaming renvoie la réponse jeton par jeton, comme une frappe en direct. On l’active avec stream=True et on itère sur les fragments reçus.

flux = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[
        {"role": "system", "content": "Tu es l'assistant interne du service informatique."},
        {"role": "user", "content": "Le serveur d'impression ne repond plus, que verifier ?"},
    ],
    stream=True,
)

for fragment in flux:
    delta = fragment.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
print()

Chaque fragment contient un petit morceau de texte dans delta.content. On le teste avant de l’afficher car le tout premier et le tout dernier fragment peuvent être vides (ils portent des métadonnées, pas du texte). Le flush=True force l’affichage immédiat sans attendre un saut de ligne. Résultat : le texte apparaît progressivement, ce qui change radicalement la perception de réactivité côté utilisateur.

Étape 4 — Tenir une conversation à plusieurs tours

L’API est sans état : le modèle ne se souvient de rien entre deux appels. Pour qu’un agent suive une conversation, c’est à vous de renvoyer l’historique complet à chaque tour. Le principe : on accumule les messages dans une liste, et on y ajoute la réponse de l’assistant avant de poser la question suivante.

historique = [
    {"role": "system", "content": "Tu es l'assistant interne du service informatique."},
]

def tour(question):
    historique.append({"role": "user", "content": question})
    r = client.chat.completions.create(
        model="deepseek-v4-flash",
        messages=historique,
        stream=False,
    )
    reponse = r.choices[0].message.content
    historique.append({"role": "assistant", "content": reponse})
    return reponse

print(tour("Mon VPN se deconnecte toutes les 5 minutes."))
print(tour("Et si je suis sur une connexion mobile ?"))

Au deuxième tour, le modèle comprend que « et si je suis sur une connexion mobile » se rapporte au problème de VPN, parce que l’historique le lui rappelle. Attention : plus l’historique grossit, plus chaque appel coûte cher en jetons d’entrée. Pour une conversation longue, pensez à tronquer les anciens messages ou à résumer périodiquement le contexte.

Étape 5 — Comprendre le coût et le cache de contexte

Chaque réponse de l’API contient un objet usage qui détaille les jetons consommés. C’est l’outil indispensable pour piloter votre budget. DeepSeek facture séparément les jetons d’entrée et de sortie, et applique un tarif fortement réduit aux jetons d’entrée déjà vus récemment — c’est le cache de contexte, activé automatiquement.

r = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=historique,
)
u = r.usage
print("entree:", u.prompt_tokens, "| sortie:", u.completion_tokens)

Au moment d’écrire ces lignes, deepseek-v4-flash facture l’entrée à 0,14 $ par million de jetons en cas d’absence de cache, et seulement 0,0028 $ par million quand le cache est touché (un cinquantième du prix), tandis que la sortie est à 0,28 $ par million. À ces niveaux, des milliers de questions de support tiennent dans quelques dizaines de centimes. Le cache se déclenche tout seul lorsque le début de vos messages (typiquement la consigne système, longue et stable) se répète d’un appel à l’autre : raison de plus pour garder une consigne système constante.

Point d’étape — Vous savez maintenant lire la consommation réelle de chaque requête. Lancez deux appels identiques d’affilée : au second, prompt_tokens devrait être en grande partie facturé au tarif cache, preuve que le mécanisme fonctionne.

Étape 6 — Rendre l’appel robuste

En production, le réseau coupe, l’API peut renvoyer une erreur temporaire, ou imposer une limite de débit. Un assistant qui plante au premier hoquet est inutilisable. On encapsule donc l’appel dans une logique de nouvelles tentatives avec un délai croissant, et on fixe un délai d’attente maximal.

import time
from openai import APIError, RateLimitError, APITimeoutError

def appel_robuste(messages, tentatives=3):
    for i in range(tentatives):
        try:
            return client.chat.completions.create(
                model="deepseek-v4-flash",
                messages=messages,
                timeout=30,
                extra_body={"thinking": {"type": "disabled"}},
            )
        except (RateLimitError, APITimeoutError, APIError) as e:
            attente = 2 ** i
            print("erreur:", type(e).__name__, "- nouvelle tentative dans", attente, "s")
            time.sleep(attente)
    raise RuntimeError("echec apres plusieurs tentatives")

La boucle réessaie jusqu’à trois fois en doublant l’attente à chaque échec (1 s, 2 s, 4 s) : c’est le backoff exponentiel, la stratégie standard pour ne pas marteler un service déjà sous tension. On capture spécifiquement les erreurs de débit et de délai, qui sont récupérables, tout en laissant remonter les erreurs définitives comme une clé invalide.

Étape 7 — Assembler l’assistant et vérifier de bout en bout

On rassemble tout dans une fonction réutilisable. Elle isole la consigne système, journalise le coût, et s’appuie sur l’appel robuste de l’étape précédente.

CONSIGNE = ("Tu es l'assistant interne du service informatique. "
            "Reponds en francais, de facon concise et actionnable. "
            "Si tu n'es pas sur, dis-le et propose a qui s'adresser.")

def demander_support(question):
    messages = [
        {"role": "system", "content": CONSIGNE},
        {"role": "user", "content": question},
    ]
    r = appel_robuste(messages)
    print("[cout] entree", r.usage.prompt_tokens, "sortie", r.usage.completion_tokens)
    return r.choices[0].message.content

if __name__ == "__main__":
    print(demander_support("Comment demander un acces au dossier partage comptabilite ?"))

En lançant python assistant_support.py, vous devez obtenir une réponse structurée suivie d’une ligne de coût. C’est votre première brique fonctionnelle : une fonction unique, testée, mesurée et résistante aux pannes passagères, prête à être branchée derrière une interface web ou un bot interne.

🐞 Pièges fréquents

Symptôme / erreur Cause probable Correctif
AuthenticationError / 401 Clé absente ou mal lue dans l’environnement Vérifier echo $DEEPSEEK_API_KEY dans le terminal qui lance le script
Réponse vide ou tronquée Limite de jetons de sortie atteinte Augmenter max_tokens ou raccourcir la question
402 / solde insuffisant Crédit épuisé sur la plateforme Recréditer le solde ; l’API ne fonctionne pas à découvert
Coût qui explose Historique de conversation jamais tronqué Limiter le nombre de tours conservés ou résumer le contexte
Le cache ne se déclenche jamais Consigne système qui varie à chaque appel Garder un préfixe système strictement identique

Travailler avec un budget serré et une connexion instable

Trois réflexes maximisent la valeur de chaque appel. D’abord, plafonnez max_tokens sur la sortie : c’est elle qui coûte le plus cher, et une réponse de support n’a pas besoin d’être un roman. Ensuite, exploitez le cache en figeant la consigne système, ce qui fait fondre le coût d’entrée des requêtes répétitives. Enfin, sur une liaison capricieuse, le streaming combiné au délai d’attente de 30 secondes évite de rester bloqué : si la connexion tombe en cours de route, la logique de nouvelles tentatives reprend la main. Pour développer hors ligne ou tester sans consommer de crédit, le déploiement local d’un modèle DeepSeek est une option que nous couvrons dans un autre guide de la série.

✅ Récapitulatif

Vous êtes parti d’un compte vide et vous repartez avec une fonction demander_support() opérationnelle. En chemin, vous avez vu que l’API de DeepSeek se pilote avec le SDK d’OpenAI moyennant un simple base_url, comment streamer une réponse, comment maintenir une conversation à plusieurs tours, comment lire et réduire le coût via le cache de contexte, et comment encaisser les erreurs réseau sans planter. C’est exactement le socle sur lequel reposent les agents plus avancés.

🧾 Aide-mémoire

Élément Rôle
base_url="https://api.deepseek.com" Rediriger le client OpenAI vers DeepSeek
deepseek-v4-flash Modèle rapide et économique (choix par défaut)
deepseek-v4-pro Modèle plus capable pour les tâches difficiles
stream=True Réponse jeton par jeton
reponse.usage Jetons d’entrée et de sortie consommés
timeout=30 Délai d’attente maximal par appel

💪 À vous de jouer

Ajoutez à demander_support() un paramètre urgent=False qui, lorsqu’il vaut True, bascule sur deepseek-v4-pro et ajoute à la consigne système l’instruction de proposer une solution de contournement immédiate. Mesurez la différence de coût entre les deux modèles sur la même question.

Voir une solution
def demander_support(question, urgent=False):
    modele = "deepseek-v4-pro" if urgent else "deepseek-v4-flash"
    consigne = CONSIGNE + (" Propose d'abord un contournement immediat." if urgent else "")
    messages = [
        {"role": "system", "content": consigne},
        {"role": "user", "content": question},
    ]
    r = client.chat.completions.create(
        model=modele,
        messages=messages,
        extra_body={"thinking": {"type": "disabled"}},
    )
    return r.choices[0].message.content

Ici on appelle directement create() pour rester concis ; en production, on ferait passer ce choix de modèle par appel_robuste. Vous constaterez que pro coûte sensiblement plus en sortie, à réserver aux cas qui le méritent.

Dans la même série

Pour approfondir

FAQ

Faut-il payer pour utiliser l’API DeepSeek ?
Oui, l’API est facturée à l’usage et nécessite un solde de crédit préalable. Les tarifs comptent parmi les plus bas du marché, de l’ordre de quelques dizaines de centimes pour des milliers de requêtes courtes.

Puis-je réutiliser du code écrit pour OpenAI ?
Dans la grande majorité des cas, oui : il suffit de changer base_url et le nom du modèle. Les structures de requête et de réponse suivent le même format.

Quelle différence entre flash et pro ?
deepseek-v4-flash privilégie la vitesse et le coût, deepseek-v4-pro la capacité de raisonnement. Pour du support de premier niveau, flash suffit largement.

Comment éviter de divulguer ma clé API ?
Ne la codez jamais en dur. Lisez-la depuis une variable d’environnement ou un fichier .env exclu du dépôt Git via .gitignore.

Partager
Service ITSkillsCenter

Application mobile Android et iOS

Création d'application mobile Android et iOS. À partir de 350 000 FCFA.

Démarrer mon projet
Publicité