FR ▾
Obtenir une clé API

Exemple Python API DeepSeek : chat, streaming, outils

Une configuration API DeepSeek en Python nécessite uniquement le package openai officiel, une URL de base, une clé et un ID de modèle. Les exemples ci-dessous couvrent une requête simple, le streaming, le mode JSON, l'appel d'outils et les nouvelles tentatives, tous adressés à un endpoint compatible OpenAI.

Mis à jour le

Panneau terminal diffusant en streaming des tokens lumineux vers un bloc serveur, illustrant des appels API Python

Points clés

  • Installez openai, puis définissez base_url sur https://api.deepseekapi.top/v1 et model sur uncensored.
  • Le streaming, le mode JSON et l'appel d'outils fonctionnent via les paramètres SDK normaux.
  • Gérez le HTTP 429 en lisant Retry-After et en réessayant.
  • Le prix est de 0,15 $ par 1 M de tokens d'entrée et de 0,50 $ par 1 M de tokens de sortie.

Installer et envoyer une première requête

Ce service n'est pas l'API officielle DeepSeek. Il s'agit d'un endpoint hébergé, compatible OpenAI, qui exécute un seul modèle à poids ouverts, ID uncensored, opéré par un fournisseur indépendant. Comme il suit le format OpenAI, le SDK Python standard fonctionne sans modifications au-delà de l'URL et de la clé.

pip install openai

Obtenez une clé depuis la page Clé API. Après l’inscription, vous pouvez réclamer 0,50 $ de crédit d’essai en un clic, sans carte, valable 7 jours. Stockez la clé dans une variable d’environnement plutôt que dans le fichier source :

export API_KEY="YOUR_KEY"
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.deepseekapi.top/v1",
    api_key=os.environ["API_KEY"],
)

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "Explain list comprehensions in two sentences."},
    ],
    temperature=0.7,
)

print(resp.choices[0].message.content)
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)

Les deux chiffres d'utilisation sont ce sur quoi vous êtes facturé. Multipliez-les par les prix pour voir le coût de n'importe quel appel : tokens d'entrée fois 0,15 $ et tokens de sortie fois 0,50 $, chacun divisé par 1 000 000.

Utilisation du client asynchrone

Pour les serveurs web et tout ce qui gère de nombreux utilisateurs, utilisez le client asynchrone. Il possède les mêmes paramètres que le client synchrone et constitue un changement prêt à l’emploi dans la plupart des codes.

import asyncio
import os
from openai import AsyncOpenAI

client = AsyncOpenAI(
    base_url="https://api.deepseekapi.top/v1",
    api_key=os.environ["API_KEY"],
)

sem = asyncio.Semaphore(8)

async def ask(prompt):
    async with sem:
        r = await client.chat.completions.create(
            model="uncensored",
            messages=[{"role": "user", "content": prompt}],
        )
        return r.choices[0].message.content

async def main():
    prompts = ["Define idempotent.", "Define monotonic.", "Define pure function."]
    answers = await asyncio.gather(*(ask(p) for p in prompts))
    for a in answers:
        print(a)

asyncio.run(main())

Le sémaphore est réglé à 8 car c'est la concurrence d'une clé complète. Sur une clé d'essai, utilisez 2. Sans limite, une rafale de tâches produira des erreurs concurrency même si chaque requête est valide.

Réponses en streaming

Définissez stream=True et l’endpoint envoie des server-sent events. Chaque chunk transporte un petit morceau de texte dans delta.content. Demander l’utilisation signifie que le dernier chunk rapporte les compteurs de tokens.

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
stream = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Write a haiku about debugging."}],
    stream=True,
    stream_options={"include_usage": True},
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:
        print("\n", chunk.usage.prompt_tokens, chunk.usage.completion_tokens)

Deux détails font trébucher les gens. Le chunk d'utilisation final peut avoir une liste choices vide, c'est pourquoi la boucle vérifie d'abord chunk.choices. Et une requête en streaming conserve sa place de concurrence jusqu'à la fin du flux, alors sortez proprement des boucles et fermez les flux que vous abandonnez. Une clé complète permet 8 requêtes simultanées ; une clé d'essai en permet 2.

Mode JSON

Pour une sortie qu'un programme analysera, utilisez response_format avec json_object. Mentionnez aussi le mot JSON dans le prompt et décrivez la forme souhaitée. Le modèle a besoin de cette instruction ; le seul drapeau ne fournit pas de schéma.

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
import json

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "Reply with JSON only: {\"title\": str, \"tags\": [str]}"},
        {"role": "user", "content": "Summarize: a guide to caching HTTP responses."},
    ],
    response_format={"type": "json_object"},
    temperature=0,
)

data = json.loads(resp.choices[0].message.content)
print(data["title"], data["tags"])

Gardez un try/except autour de json.loads. Si une réponse est coupée par une limite de tokens, elle ne s'analysera pas, donc évitez un max_tokens minuscule avec du JSON. Définir temperature à 0 et un seed rend les réexécutions plus reproductibles, car les deux sont transmis.

Appel de fonctions

L'API accepte tools et tool_choice, et renvoie tool_calls sur le message de l'assistant. Vous exécutez la fonction vous-même et renvoyez le résultat sous forme de message avec role: "tool".

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
import json

tools = [{
    "type": "function",
    "function": {
        "name": "add",
        "description": "Add two numbers.",
        "parameters": {
            "type": "object",
            "properties": {"a": {"type": "number"}, "b": {"type": "number"}},
            "required": ["a", "b"],
        },
    },
}]

messages = [{"role": "user", "content": "What is 17.5 plus 24.25?"}]
first = client.chat.completions.create(
    model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)

msg = first.choices[0].message
if msg.tool_calls:
    messages.append(msg)
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = args["a"] + args["b"]
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": str(result),
        })
    final = client.chat.completions.create(
        model="uncensored", messages=messages, tools=tools
    )
    print(final.choices[0].message.content)
else:
    print(msg.content)

Analysez toujours arguments de manière défensive. Il s'agit d'une chaîne JSON produite par le modèle, et une chaîne malformée est possible. Validez-la avant d'agir dessus, surtout si la fonction touche à des fichiers ou à une base de données.

Erreurs, limites et nouvelles tentatives

Une requête dépassant une limite renvoie HTTP 429. Le code d'erreur indique quelle limite : rate_limited pour les requêtes par minute (300 sur une clé complète, 60 sur une clé d'essai) et concurrency pour trop de requêtes à la fois. En cas de surcharge temporaire, vous obtenez également 429 avec Retry-After: 5. Le SDK lève openai.RateLimitError.

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
import time
import openai

def ask(prompt, tries=4):
    for attempt in range(tries):
        try:
            r = client.chat.completions.create(
                model="uncensored",
                messages=[{"role": "user", "content": prompt}],
            )
            return r.choices[0].message.content
        except openai.RateLimitError as e:
            wait = int(e.response.headers.get("Retry-After", 5))
            time.sleep(wait * (attempt + 1))
    raise RuntimeError("still rate limited")

print(ask("Name three Python web frameworks."))

Si vous envoyez beaucoup de requêtes, limitez votre propre parallélisme avec un sémaphore ou un thread pool de 8 workers, ou 2 sur une clé d’essai. Cela évite les erreurs concurrency au lieu de les gérer par retry.

Lecture des en-têtes

Chaque réponse transporte X-Request-Id, X-Balance-USD, X-RateLimit-Limit-Requests et X-RateLimit-Limit-Concurrency. Le SDK les expose via la réponse brute :

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
raw = client.chat.completions.with_raw_response.create(
    model="uncensored",
    messages=[{"role": "user", "content": "ping"}],
)
print(raw.headers.get("X-Balance-USD"), raw.headers.get("X-Request-Id"))
completion = raw.parse()

Journaliser l'ID de requête avec chaque échec rend les questions de support beaucoup plus faciles à traiter. Les requêtes échouées ou refusées ne sont pas facturées.

Maintenir une conversation

L'API est sans état. Elle ne se souvient pas des requêtes précédentes, donc une conversation multi-tours signifie que vous envoyez tout l'historique à chaque fois. Gardez une liste et ajoutez-y :

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
history = [{"role": "system", "content": "You are a helpful tutor."}]

def chat(user_text):
    history.append({"role": "user", "content": user_text})
    r = client.chat.completions.create(model="uncensored", messages=history)
    reply = r.choices[0].message.content
    history.append({"role": "assistant", "content": reply})
    return reply

print(chat("What is a closure?"))
print(chat("Show me one in Python."))

Chaque tour renvoie tout, donc les tokens d'entrée augmentent tour par tour. Supprimez les anciens messages une fois que la liste devient longue, ou demandez au modèle de résumer la partie ancienne et de la remplacer. Avec une fenêtre de 100 000 tokens, vous avez beaucoup de place, mais la facture augmente avec l'historique, donc une liste tronquée est moins chère.

Choix des valeurs d'échantillonnage

Utilisez temperature 0 à 0,3 pour le code et l'extraction, environ 0,7 pour le chat général, et plus élevé pour la fiction. top_p, stop, seed et les pénalités de fréquence et de présence sont transmises, donc elles se comportent comme décrit dans la documentation OpenAI. Modifiez une valeur à la fois et comparez.

Planification du coût et du contexte

La fenêtre de contexte est de 100 000 tokens, prompt plus complétion, et la limite du corps est de 8 Mo. La complétion peut utiliser tout ce qui reste de la fenêtre, et max_tokens est facultatif. Le définir reste une bonne pratique pour les travaux par lots.

Un exemple concret : un lot de 1 000 résumés, chacun avec 1 500 tokens d'entrée et 200 tokens de sortie.

  • Entrée : 1 000 × 1 500 = 1 500 000 tokens, soit 1,5 × 0,15 $ = 0,225 $
  • Sortie : 1 000 × 200 = 200 000 tokens, soit 0,2 × 0,50 $ = 0,10 $
  • Total : 0,325 $

La tarification est en paiement à l'usage depuis un crédit prépayé, sans abonnement, et le crédit n'expire jamais. Les recharges vont de 20 $ à 500 $ en montants entiers, avec +5 % à partir de 50 $, +10 % à partir de 100 $ et +15 % à partir de 200 $, payables par carte ou crypto. Consultez la page de tarification, et la documentation de démarrage rapide pour les exemples curl et Node. Si vous avez juste besoin de localiser votre clé, la vue d'ensemble de la clé API le couvre.

Les prompts ne sont pas utilisés pour l'entraînement. Le service est textuel uniquement : pas d'images, audio, embeddings ou fine-tuning, donc ne prévoyez pas autour de ces endpoints.

Questions et réponses

Faut-il une bibliothèque DeepSeek spéciale ?

Non. Installez le package openai, définissez base_url sur https://api.deepseekapi.top/v1 et utilisez l'ID de modèle uncensored. Il ne s'agit pas de l'API officielle DeepSeek.

Le SDK Python prend-il en charge le streaming ici ?

Oui. Passez stream=True et ajoutez stream_options avec include_usage pour obtenir les compteurs de tokens dans le dernier chunk.

Comment gérer une erreur 429 ?

Attrapez openai.RateLimitError, lisez l'en-tête Retry-After et attendez avant de réessayer. Le code d'erreur indique s'il s'agit d'une limite de débit ou de concurrence.

Puis-je tester sans payer ?

Oui. Après l’inscription, un clic sur la page Clé API ajoute 0,50 $ de crédit d’essai, valable 7 jours, sans carte requise.

Votre clé n'est qu'à un formulaire de distance

Créez un compte, copiez la clé, modifiez l'URL de base. C'est toute la configuration.

Obtenir une clé API