ES ▾
Obtener clave de API

Ejemplo de API DeepSeek en Python: chat, streaming y herramientas

Una configuración de api python de deepseek solo necesita el paquete openai oficial, una base URL, una clave y un ID de modelo. Los ejemplos siguientes cubren una petición simple, streaming, modo JSON, llamadas a herramientas y reintentos, todos contra un endpoint compatible con OpenAI.

Actualizado

Slab de terminal transmitiendo tokens de datos brillantes a un bloque de servidor, representando llamadas a la API de Python

Puntos clave

  • Instala openai, luego establece base_url en https://api.deepseekapi.top/v1 y model en uncensored.
  • El streaming, el modo JSON y las llamadas a herramientas funcionan a través de los parámetros normales del SDK.
  • Maneja el HTTP 429 leyendo Retry-After e intentando de nuevo.
  • El precio es $0,15 por 1M de tokens de entrada y $0,50 por 1M de tokens de salida.

Instalación y envío de la primera petición

Este servicio no es la API oficial de DeepSeek. Es un endpoint alojado y compatible con OpenAI que ejecuta un único modelo de pesos abiertos, ID uncensored, operado por un proveedor independiente. Como sigue el formato de OpenAI, el SDK de Python estándar funciona sin cambios más allá de la URL y la clave.

pip install openai

Obtén una clave desde la página clave de API. Tras registrarte puedes reclamar $0,50 de crédito de prueba con un clic, sin tarjeta, válido por 7 días. Almacena la clave en una variable de entorno en lugar del archivo fuente:

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)

Los dos números de uso son sobre los que se te cobra. Multiplícalos por los precios para ver el coste de cualquier llamada: tokens de entrada por $0,15 y tokens de salida por $0,50, cada uno dividido por 1.000.000.

Uso del cliente asíncrono

Para servidores web y cualquier cosa que maneje muchos usuarios, usa el cliente asíncrono. Tiene los mismos parámetros que el síncrono y es un cambio listo para usar en la mayoría del código.

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())

El semáforo se establece en 8 porque esa es la concurrencia de una clave completa. En una clave de prueba usa 2. Sin un límite, una ráfaga de tareas producirá errores de concurrency aunque cada petición sea válida.

Respuestas en streaming

Establece stream=True y el endpoint envía eventos enviados por el servidor. Cada bloque lleva un pequeño fragmento de texto en delta.content. Pedir uso significa que el último bloque reporta recuentos 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)

Dos detalles suelen causar problemas. El fragmento final de uso puede tener una lista choices vacía, por eso el bucle comprueba chunk.choices primero. Y una petición en streaming mantiene su slot de concurrencia hasta que termina el flujo, así que sal de los bucles de forma limpia y cierra los flujos que abandones. Una clave completa permite 8 peticiones simultáneas; una clave de prueba permite 2.

Modo JSON

Para salida que un programa analizará, usa response_format con json_object. También indica la palabra JSON en el prompt y describe la forma que deseas. El modelo necesita esa instrucción; la bandera por sí sola no proporciona un esquema.

# 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"])

Envuelve try/except alrededor de json.loads. Si una respuesta se corta por un límite de tokens, no se analizará, así que evita un max_tokens muy pequeño con JSON. Establecer temperature en 0 y un seed hace que las repeticiones sean más reproducibles, ya que ambos se propagan.

Llamadas a funciones

La API acepta tools y tool_choice, y devuelve tool_calls en el mensaje del asistente. Ejecutas la función tú mismo y envías el resultado de vuelta como un mensaje con 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)

Analiza siempre arguments de forma defensiva. Es una cadena JSON producida por el modelo, y es posible que una cadena esté mal formada. Valídala antes de actuar sobre ella, especialmente si la función toca archivos o una base de datos.

Errores, límites y reintentos

Una petición por encima de un límite devuelve HTTP 429. El código de error te dice qué límite: rate_limited para peticiones por minuto (300 en una clave completa, 60 en una clave de prueba) y concurrency para demasiadas a la vez. En sobrecarga temporal también obtienes 429 con Retry-After: 5. El SDK lanza 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 envías muchas peticiones, limita tu propia paralelización con un semáforo o un grupo de hilos de 8 trabajadores, o 2 en una clave de prueba. Eso evita errores de concurrency en lugar de reintentar a través de ellos.

Lectura de encabezados

Cada respuesta lleva X-Request-Id, X-Balance-USD, X-RateLimit-Limit-Requests y X-RateLimit-Limit-Concurrency. El SDK los expone a través de la respuesta cruda:

# 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()

Registrar el ID de petición con cada fallo hace que las preguntas de soporte sean mucho más fáciles de responder. Las peticiones fallidas o rechazadas no se cobran.

Mantener una conversación

La API es sin estado. No recuerda las peticiones anteriores, así que un chat de varios turnos significa que envías todo el historial cada vez. Mantén una lista y añádele elementos:

# 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."))

Cada turno reenvía todo, así que los tokens de entrada crecen turno a turno. Recorta los mensajes antiguos una vez que la lista sea larga, o pide al modelo que resuma la parte inicial y reemplázala. Con una ventana de 100.000 tokens tienes mucho espacio, pero la factura crece con el historial, así que una lista recortada es más barata.

Elección de valores de muestreo

Usa temperature de 0 a 0,3 para código y extracción, alrededor de 0,7 para chat general y valores más altos para ficción. top_p, stop, seed y las penalizaciones de frecuencia y presencia se reenvían, por lo que se comportan como describe la documentación de OpenAI. Cambia uno a la vez y compara.

Planificación de costes y contexto

La ventana de contexto es de 100.000 tokens, prompt más completación, y el límite del cuerpo es de 8 MB. La completación puede usar lo que quede de la ventana, y max_tokens es opcional. Establecerlo sigue siendo una buena práctica para trabajos por lotes.

Un ejemplo práctico: un lote de 1.000 resúmenes, cada uno con 1.500 tokens de entrada y 200 tokens de salida.

  • Entrada: 1.000 × 1.500 = 1.500.000 tokens, que es 1,5 × $0,15 = $0,225
  • Salida: 1.000 × 200 = 200.000 tokens, que es 0,2 × $0,50 = $0,10
  • Total: $0,325

La facturación es de pago por uso desde el crédito prepago, sin suscripción, y el crédito no caduca. Las recargas van desde $20 hasta $500 en montos enteros, con +5% desde $50, +10% desde $100 y +15% desde $200, pagaderos con tarjeta o cripto. Consulta la página de precios y la documentación de inicio rápido para ejemplos con curl y Node. Si solo necesitas localizar tu clave, la visión general de la clave de API la cubre.

Los prompts no se usan para entrenamiento. El servicio es solo texto: sin imágenes, audio, embeddings ni ajuste fino, así que no planifiques en torno a esos endpoints.

Preguntas y respuestas

¿Necesito una biblioteca especial de DeepSeek?

No. Instala el paquete openai, establece base_url en https://api.deepseekapi.top/v1 y usa el ID de modelo uncensored. Esta no es la API oficial de DeepSeek.

¿El SDK de Python admite streaming aquí?

Sí. Pasa stream=True y añade stream_options con include_usage para obtener recuentos de tokens en el último fragmento.

¿Cómo manejo un error 429?

Captura openai.RateLimitError, lee la cabecera Retry-After y espera antes de reintentar. El código de error te indica si fue rate_limited o por concurrencia.

¿Puedo probar sin pagar?

Sí. Tras registrarte, un clic en la página de clave de API añade $0,50 de crédito de prueba, válido por 7 días, sin necesidad de tarjeta.

Tu clave está a un formulario de distancia

Crea una cuenta, copia la clave, cambia la URL base. Esa es toda la configuración.

Obtener clave de API