Desarrollo de API de IA
Usar herramientas de chat de IA en la interfaz web es muy conveniente, pero para integrar realmente las capacidades de IA en tus propios productos, flujos de trabajo y scripts de automatización, necesitas una API.
API (Application Programming Interface) es el puente de comunicación entre aplicaciones. A través de la API, tu código puede enviar solicitudes directamente a un modelo de IA y obtener respuestas, sin necesidad de abrir una página web manualmente para copiar y pegar.
Imagina estos escenarios:
Tu sitio web de comercio electrónico genera automáticamente descripciones para cada producto.
-
Tu aplicación de notas resume automáticamente los textos largos introducidos por el usuario.
-
Tu sistema de atención al cliente clasifica y responde automáticamente las consultas de los usuarios.
-
Todas estas funciones se pueden implementar mediante la API de IA.
El objetivo de este módulo es llevarte de «solo saber chatear con IA» a «poder hacer que la IA trabaje dentro de tu código».
Conceptos básicos de API
Antes de escribir código, primero comprendamos algunos conceptos clave.
¿Qué es una API?
Una API es una forma de comunicación predefinida: enviamos solicitudes en un formato específico y la otra parte devuelve resultados en un formato específico.
Usemos el pedido de comida como ejemplo:
-
Entras en un restaurante, recibes el menú (documentación de la API) y sabes qué puedes pedir y cómo pedirlo (formato de solicitud).
-
Le dices al camarero: un plato de pollo Kung Pao, poco picante (envías la solicitud a la API).
-
La cocina prepara el plato y te lo sirve (recibes la respuesta de la API).
En este proceso, no necesitas entrar en la cocina ni saber cómo se prepara el plato: este es el valor de la API:Encapsular los detalles complejos y exponer solo interfaces simples。
Principios básicos de la API REST
REST (Representational State Transfer) es el estilo de diseño de API más popular en la actualidad.
En pocas palabras, es comunicarse mediante el protocolo HTTP:
| Método HTTP | Uso | Ejemplo en la API de IA |
|---|---|---|
| POST | Crear recurso | Enviar solicitudes de chat, generar imágenes |
| GET | Obtener recurso | Consultar la lista de modelos, obtener información de facturación |
| DELETE | Eliminar recurso | Eliminar el historial de conversación |
La gran mayoría de las API de IA son solicitudes POST, porque necesitamos «enviar contenido a la IA para que lo procese».
Introducción al formato JSON
JSON (JavaScript Object Notation) es el formato de datos más utilizado en la comunicación con API.
La sintaxis de JSON es muy sencilla: es una combinación de pares clave-valor.
Ejemplo
"model": "gpt-4",
"messages": [
{
"role": "user",
"content": Hola, por favor preséntame EJEMPLO.
}
],
"temperature": 0.7,
"max_tokens": 1000
}
Este es un cuerpo de solicitud típico de una API de IA.
Algunas reglas fundamentales:
-
Los objetos se envuelven usando
{ }como delimitador, y los arrays se envuelven usando[ ]como delimitador. -
Las cadenas se escriben usando comillas dobles
"y no se pueden usar comillas simples. -
Los pares clave-valor se separan usando
:como separador, y la clave debe ser una cadena. -
Los múltiples pares clave-valor se separan usando
,como separador.
JSON se parece mucho a los diccionarios de Python, pero hay diferencias en la sintaxis; ten cuidado al escribir código.
Preparación del entorno de desarrollo
Para hacer bien un trabajo, primero hay que afilar las herramientas.
Instalación y configuración de Python
Python es el lenguaje más utilizado para llamar a la API de IA, con un ecosistema completo y una gran cantidad de librerías.
Primero verifica si Python está instalado en tu computadora:
# 检查 Python 版本(Windows、macOS、Linux 通用) python --version # 或者 python3 --version
Se recomienda usar Python 3.9 o superior.
Si aún no lo has instalado, ve apython.orgDescarga la última versión estable.
Gestión de paquetes con pip
pip es el gestor de paquetes de Python que se utiliza para instalar librerías de terceros.
# 检查 pip 版本 pip --version # 或者 pip3 --version # 升级 pip 到最新版本 pip install --upgrade pip # 配置国内镜像源(可选,提升下载速度) pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
Elección del editor de código
Para escribir código de API de IA, se recomiendan uno de los siguientes editores:
| Editor | Características | Público objetivo |
|---|---|---|
| VS Code | Gratuito, con abundantes complementos y ligero | La mayoría de los desarrolladores |
| Cursor | Asistencia de IA integrada, puede generar código directamente | Para quienes desean que la IA les ayude a escribir código |
| PyCharm | La más completa en funciones y con el mejor soporte para Python | Desarrolladores profesionales de Python |
Los códigos de ejemplo de este tutorial se pueden ejecutar en cualquier editor.
Introducción a la API de OpenAI
La API de OpenAI es la API de IA más clásica y con el ecosistema más completo; muchos otros proveedores también son compatibles con su formato.
Registro y obtención de la API Key
La API Key es tu pase de acceso: acredita tu identidad y registra tu uso. Pasos para obtenerla:
-
1. Visitaplatform.openai.comCrea una cuenta
-
2. Ve a la página de API Keys
-
3. Haz clic en «Create new secret key»
-
4. Copia y guarda esta Key (¡solo se muestra una vez!)
Importante:Nunca subas tu API Key a un repositorio de código público. Si se filtra, otros podrían utilizar tu cuota y generar cargos.
La primera llamada a la API
Primero instala el SDK oficial de OpenAI:
pip install openai
Ahora escribe el primer programa de llamada a la API:
Ejemplo
# Primer ejemplo de llamada a la API de OpenAI
from openai import OpenAI
# Inicializar el cliente
# Nota: se recomienda leer la API Key desde una variable de entorno, no codificarla directamente en el código.
# Aquí se escribe directamente para simplificar la demostración; en proyectos reales, use variables de entorno.
client = OpenAI(
api_key="your-api-key-here" # Reemplaza con tu API Key
)
# Enviar solicitud de chat
response = client.chat.completions.create(
model="gpt-3.5-turbo", # Seleccionar modelo
messages=[
{
"role": "user", # Rol: 'user' representa al usuario
"content": Presenta el tutorial EJEMPLO para novatos en una sola frase # Contenido ingresado por el usuario
}
]
)
# Imprime la respuesta completa (para ver qué devuelve)
print(Respuesta completa:)
print(response)
print("\n" + "="*50 + "\n")
# Extraer la respuesta de la IA
ai_reply = response.choices[0].message.content
print("AI responde:")
print(ai_reply)
Si no tienes una api_key de OpenAI, también puedes usar alternativas nacionales. Muchos modelos nacionales son compatibles con OpenAI, como DeepSeek. Puedes ir ahttps://platform.deepseek.com/api_keysSolicita una api_key y luego reemplaza la tuya en el siguiente códigoapi_keyymodel, los modelos compatibles con DeepSeek son deepseek-v4-flash y deepseek-v4-pro (modo de pensamiento). Así puedes usar la API para llamar al modelo grande:
Ejemplo
# Inicializar el cliente
# Nota: se recomienda leer la API Key desde variables de entorno, no la codifiques en el código
# Aquí se escribió directamente por conveniencia de la demostración, en proyectos reales usa variables de entorno
client = OpenAI(
api_key="sk-xxxx", # Establecer api_key
base_url="https://api.deepseek.com") # Establecer la URL de la solicitud
# Enviar solicitud de chat
response = client.chat.completions.create(
model="deepseek-v4-flash", # Seleccionar modelo
messages=[
{
"role": "user", # Rol: user representa al usuario
"content": "Presenta EJEMPLO, el tutorial para novatos, en una frase" # Contenido ingresado por el usuario
}
]
)
# Imprimir la respuesta completa (para ver qué devolvió)
print("Respuesta completa:")
print(response)
print("\n" + "="*50 + "\n")
# Extraer la respuesta de la IA
ai_reply = response.choices[0].message.content
print("Respuesta de la IA:")
print(ai_reply)
Ejecuta este programa:
python first_api_call.py
Si todo funciona bien, verás una salida similar a esta:
完整响应: ChatCompletion( id='chatcmpl-xxx', choices=[Choice(finish_reason='stop', index=0, message=ChatMessage(content='Ejemplo是一个专注于提供编程技术教程的学习平台...', role='assistant'))], model='gpt-3.5-turbo', usage=CompletionUsage(completion_tokens=30, prompt_tokens=18, total_tokens=48) ) ================================================== AI 回复: Ejemplo是一个专注于提供编程技术教程的学习平台,涵盖多种编程语言和技术领域。
¡Felicitaciones! Has llamado correctamente a una API de IA una vez.
Explicación detallada de los parámetros de solicitud
La API de OpenAI tiene muchos parámetros ajustables, a continuación se muestran los más comunes:
| Nombre del parámetro | Tipo | Obligatorio | Descripción | Valor por defecto |
|---|---|---|---|---|
| model | string | Sí | ID del modelo utilizado, como gpt-3.5-turbo, gpt-4 | Ninguno |
| messages | array | Sí | Lista de mensajes del historial de conversación | Ninguno |
| temperature | number | no | Temperatura de muestreo, entre 0-2, cuanto más alta más aleatorio, más baja más determinista | 1.0 |
| max_tokens | integer | no | Número máximo de tokens a generar | Sin límite |
| top_p | number | no | Parámetro de muestreo de núcleo (top_p), entre 0-1 | 1.0 |
| stop | string/array | no | Secuencia de parada, detiene la generación al encontrar estos caracteres | null |
Hablemos especialmente de temperature, es el parámetro de ajuste más usado:
Ejemplo
# Demostrar el efecto del parámetro temperature en la salida
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
def ask_ai(temperature_value: float, question: str) -> str:
"""Especificar temperature en la pregunta"""
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": question}],
temperature=temperature_value,
max_tokens=200
)
return response.choices[0].message.content
# La misma pregunta, hecha tres veces con diferentes temperature
question = "Crea un eslogan para EJEMPLO"
print("--- temperature=0 (más determinista, los resultados son casi iguales cada vez) ---")
print(ask_ai(0.0, question))
print("\n--- temperature=0.7 (equilibrado, recomendado para uso diario)---")
print(ask_ai(0.7, question))
print("\n--- temperature=1.8 (más aleatorio, gran diferencia entre resultados)---")
print(ask_ai(1.8, question))
Una regla general:
-
temperature=0: respuestas basadas en hechos, generación de código, escenarios que requieren resultados precisos
-
temperature=0.7: conversación diaria, tareas generales
-
temperature>1.0: escritura creativa, lluvia de ideas
Anthropic Claude API
Claude es el gran modelo de la empresa Anthropic, conocido por su seguridad y su capacidad para procesar textos largos.
Similitudes y diferencias con la API de OpenAI
Ambos pueden generar texto, pero sus filosofías de diseño difieren:
| Elemento de comparación | OpenAI API | Claude API |
|---|---|---|
| Estructura de mensajes | Alternancia de system, user, assistant | system se configura por separado, alternancia de user, assistant |
| Longitud del contexto | Varía entre 16k y 128k | La serie Claude 3 admite 200k |
| Diseño de parámetros | temperature, top_p, etc. | temperature, top_p, etc., conceptos similares |
Estructura de la API de Claude Messages
Primero instala el SDK de Claude:
pip install anthropic
Llamada básica de la API de Claude:
Ejemplo
# Ejemplo de llamada básica a la API de Claude
import anthropic
# Inicializar el cliente
client = anthropic.Anthropic(
api_key="your-api-key-here" # Reemplaza con tu API Key de Claude
)
# Enviar solicitud de mensaje
response = client.messages.create(
model="claude-3-sonnet-20240229", # Seleccionar modelo de Claude
max_tokens=1024, # Claude requiere que se establezca max_tokens
messages=[
{
"role": "user",
"content": "Presenta EJEMPLO (el tutorial para novatos) en tres frases"
}
]
)
# Imprimir la respuesta
print("Respuesta completa:")
print(response)
print("\n" + "="*50 + "\n")
# Extraer la respuesta
print("Respuesta de Claude:")
print(response.content[0].text)
De igual manera podemos reemplazarlo por un gran modelo nacional compatible, como DeepSeek, especificandoapi_key 、 base_url、modelestos tres parámetros:
Ejemplo
# Inicializar el cliente
client = anthropic.Anthropic(
api_key="sk-xxx", # Reemplaza con tu API Key
base_url="https://api.deepseek.com/anthropic" # URL base de la API de Claude
)
# Enviar solicitud de mensaje
response = client.messages.create(
model="deepseek-v4-flash", # Seleccionar modelo de Claude
max_tokens=1024, # Claude requiere que se establezca max_tokens
messages=[
{
"role": "user",
"content": "Presenta EJEMPLO (el tutorial para novatos) en tres frases"
}
]
)
# Imprimir la respuesta
print("Respuesta completa:")
print(response)
print("\n" + "="*50 + "\n")
# Extraer la respuesta
print("Respuesta de Claude:")
print(response.content[0].thinking)
Configuración del System Prompt
En la API de Claude, el System Prompt es un parámetro independiente, no se coloca en el array de messages:
Ejemplo
# Ejemplo de uso del System Prompt de Claude
import anthropic
client = anthropic.Anthropic(api_key="your-api-key-here")
response = client.messages.create(
model="claude-3-sonnet-20240229",
max_tokens=1024,
# El System Prompt se configura aquí
system="Eres un editor profesional de documentación técnica, responde de forma concisa y precisa, usa listas con frecuencia.",
messages=[
{
"role": "user",
"content": "¿Cuáles son los conocimientos básicos que se deben dominar para aprender Python?"
}
]
)
print(response.content[0].text)
Gestión de conversaciones de múltiples turnos
Las conversaciones de un solo turno son simples, pero las aplicaciones realmente útiles necesitan "recordar el contexto".
Métodos de mantenimiento del historial de conversación
La idea es muy simple:Guarda todas las conversaciones anteriores y envíalas junto con cada solicitud a la IA。
Ejemplo
# Ejemplo de gestión de conversaciones de múltiples turnos
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
class ChatBot:
"""Un simple robot de conversación de múltiples turnos"""
def __init__(self, system_prompt: str = "Eres un asistente servicial"):
self.messages = [] # Guardar el historial de conversación en una lista
# Primero agregar el system prompt
self.messages.append({
"role": "system",
"content": system_prompt
})
def chat(self, user_input: str) -> str:
"""Enviar mensaje y obtener respuesta"""
# Agregar mensaje del usuario al historial
self.messages.append({
"role": "user",
"content": user_input
})
# Llamar a la API
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=self.messages
)
# Obtener respuesta de la IA
ai_reply = response.choices[0].message.content
# Agregar también la respuesta de la IA al historial
self.messages.append({
"role": "assistant",
"content": ai_reply
})
return ai_reply
def get_history(self) -> list:
"""Obtener el historial de conversación"""
return self.messages
# Ejemplo de uso
if __name__ == "__main__":
bot = ChatBot(system_prompt="Eres un asistente de programación, especializado en responder preguntas sobre EJEMPLO y Python")
print("=== Demostración de conversación de múltiples turnos ===")
# Primera ronda
r1 = bot.chat("¿Qué es Python?")
print("Usuario: ¿Qué es Python?")
print("AI:", r1)
print()
# Segunda ronda (la IA puede recordar el tema de la ronda anterior)
r2 = bot.chat("¿Qué características tiene?")
print("Usuario: ¿Qué características tiene?")
print("AI:", r2)
print()
# Tercera ronda
r3 = bot.chat("¿Hay algún tutorial de Python en EJEMPLO?")
print("Usuario: ¿Hay algún tutorial de Python en EJEMPLO?")
print("AI:", r3)
Punto clave: el historial de conversación es una lista ordenada, estrictamente alternando user-assistant-user-assistant, en cada solicitud se debe enviar el historial completo para que la IA pueda entender el contexto. El historial consume tokens, por lo que debe limpiarse periódicamente.
Manejo de la superación de la ventana de contexto
Cada modelo tiene un límite de ventana de contexto, por ejemplo gpt-3.5-turbo es 16k, gpt-4 es 8k o 32k.
Cuando el historial de conversación es demasiado largo, se produce un error.
Algunas estrategias comunes de manejo:
Ejemplo
# Ejemplo de estrategia de gestión de la ventana de contexto
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
class ChatBotWithContextLimit:
"""Robot de conversación con límite de contexto"""
def __init__(self, system_prompt: str, max_messages: int = 10):
self.system_prompt = system_prompt
self.max_messages = max_messages # Cuántos mensajes conservar como máximo
self.messages = []
def _trim_messages(self):
"""Recortar la lista de mensajes, conservar los más recientes"""
# Conservar siempre el system prompt, y luego solo los últimos max_messages
if len(self.messages) > self.max_messages:
# Conservar los últimos N
self.messages = self.messages[-self.max_messages:]
def chat(self, user_input: str) -> str:
# Agregar mensaje del usuario
self.messages.append({
"role": "user",
"content": user_input
})
# Recortar el historial
self._trim_messages()
# Construir la solicitud completa (system prompt + historial)
full_messages = [
{"role": "system", "content": self.system_prompt}
] + self.messages
try:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=full_messages
)
ai_reply = response.choices[0].message.content
self.messages.append({
"role": "assistant",
"content": ai_reply
})
return ai_reply
except Exception as e:
# Si sigue dando error, puede ser necesario un recorte más agresivo
return f"Error: {str(e)}"
# Estrategia 2: Usar IA para resumir el historial de conversaciones
def summarize_conversation(messages: list) -> str:
"""Usar IA para resumir el historial de conversaciones, reemplazando el historial original"""
history_text = "\n".join([
f"{m['role']}: {m['content']}"
for m in messages
])
prompt = f"""Por favor, resume la siguiente conversación en un resumen conciso, conservando la información clave:
{history_text}
Resumen: """
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
return response.choices[0].message.content
# Usar la estrategia de resumen
print("--- Ejemplo de resumen del historial de conversación ---")
sample_history = [
{"role": "user", "content": "¿Cómo me llamo?"},
{"role": "assistant", "content": "Lo siento, no sé cómo te llamas. Puedes decírmelo."},
{"role": "user", "content": "Me llamo Xiao Ming, estoy aprendiendo Python en EJEMPLO."},
{"role": "assistant", "content": "¡Hola Xiao Ming! Encantado de conocerte. EJEMPLO es una excelente plataforma de aprendizaje."},
{"role": "user", "content": "Quiero aprender listas, ¿puedes enseñarme?"},
{"role": "assistant", "content": "¡Por supuesto! Las listas de Python son..."},
]
summary = summarize_conversation(sample_history)
print("Resumen de la conversación:", summary)
Resumiendo los métodos de gestión del contexto:
| Estrategia | Ventajas | Desventajas | Escenarios aplicables |
|---|---|---|---|
| Conservar solo los últimos N mensajes | Sencillo, rápido | Puede perder información importante | Conversaciones cortas, escenarios de charla informal |
| Usar IA para resumir el historial | Conserva la información semántica | Requiere llamadas adicionales a la API | Conversaciones largas, con mucha información importante |
| Ventana deslizante | Equilibra simplicidad y completitud | Implementación ligeramente compleja | Adecuada para escenarios generales |
Salida en streaming
Cuando chateas con IA en una página web, verás que el texto aparece palabra por palabra: esto es la salida en streaming.
¿Qué es la salida en streaming?
-
Modo normal: la IA genera la respuesta completa y la devuelve de una vez; puede que tengas que esperar varios segundos o incluso decenas de segundos.
-
Modo streaming: la IA envía cada token tan pronto como lo genera, ofreciendo una mejor experiencia de usuario.
Técnicamente, la salida en streaming utiliza el protocolo SSE (Server-Sent Events), donde el servidor envía datos de forma continua.
Implementación del efecto de máquina de escribir
Ejemplo
# Demostración de salida en streaming (efecto máquina de escribir)
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
print("=== Demostración de salida en streaming ===")
print("Pregunta: escribe una introducción sobre EJEMPLO\n")
print("Respuesta: ", end="", flush=True)
# Parámetro clave: stream=True
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": "Escribe una introducción sobre EJEMPLO, el tutorial para novatos"}
],
stream=True # Habilitar la salida en streaming
)
collected_reply = []
for chunk in response:
# Extraer el contenido del chunk actual
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
print(content, end="", flush=True) # Imprimir en tiempo real, sin salto de línea
collected_reply.append(content)
print() # Finalmente, generar un salto de línea
print("\n" + "="*50)
print("Respuesta completa:", "".join(collected_reply))
Al ejecutar este programa, verás cómo el texto aparece palabra por palabra.
El uso de la salida en streaming de Claude es similar:
Ejemplo
# Ejemplo de salida en streaming de Claude
import anthropic
client = anthropic.Anthropic(api_key="your-api-key-here")
print("=== Salida en streaming de Claude ===")
print("Pregunta: ¿cómo aprender programación?\n")
print("Respuesta: ", end="", flush=True)
with client.messages.stream(
model="claude-3-sonnet-20240229",
max_tokens=1024,
messages=[{"role": "user", "content": "¿Cómo aprender programación de manera sistemática?"}]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print()
Recomendación de experiencia de usuario: salvo que sea un escenario que requiera "esperar el resultado completo", prioriza el uso de la salida en streaming. Permitir que el usuario vea el progreso mejora significativamente la experiencia.
Cálculo y optimización de costos de API
Las API de IA se facturan según el uso; cuanto más se usan, más se gasta.
Principios de facturación de tokens
Las API de IA no se facturan por número de palabras o conversaciones, sino por tokens.Token,TokenLos tokens son la unidad básica del texto que la IA procesa.
Un token equivale aproximadamente a:
Inglés: 0.75 palabras (o 4 letras)
-
Chino: 1-2 caracteres chinos
Por ejemplo:
-
"Hello, mundo" — aproximadamente 3-4 tokens
-
El tutorial de EJEMPLO es excelente
Método de facturación:
Prompt tokens(你发给 AI 的) + Completion tokens(AI 返回给你的)= 总 tokens
Los precios varían según el modelo, por ejemplo, gpt-3.5-turbo cuesta $0.0015/1k tokens de prompt y $0.002/1k tokens de completion.
Cómo controlar los costos de API
Ejemplo
# Ejemplo de seguimiento y control de costos de API
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
# Tabla de precios de modelos (ejemplo, consulte la documentación oficial para precios reales)
# Unidad: dólares / 1k tokens
MODEL_PRICES = {
"gpt-3.5-turbo": {
"prompt": 0.0015,
"completion": 0.002
},
"gpt-4": {
"prompt": 0.03,
"completion": 0.06
}
}
def chat_with_cost_tracking(model: str, messages: list):
"""Chat con cálculo de costos"""
response = client.chat.completions.create(
model=model,
messages=messages
)
# Obtener el uso de tokens de la respuesta
usage = response.usage
prompt_tokens = usage.prompt_tokens
completion_tokens = usage.completion_tokens
total_tokens = usage.total_tokens
# Calcular el costo
price = MODEL_PRICES.get(model, {"prompt": 0, "completion": 0})
prompt_cost = (prompt_tokens / 1000) * price["prompt"]
completion_cost = (completion_tokens / 1000) * price["completion"]
total_cost = prompt_cost + completion_cost
return {
"reply": response.choices[0].message.content,
"usage": {
"prompt_tokens": prompt_tokens,
"completion_tokens": completion_tokens,
"total_tokens": total_tokens
},
"cost": {
"prompt_cost": prompt_cost,
"completion_cost": completion_cost,
"total_cost": total_cost
}
}
# Ejemplo de uso
if __name__ == "__main__":
result = chat_with_cost_tracking(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Presenta EJEMPLO"}]
)
print("Respuesta de IA:", result["reply"])
print()
print("Estadísticas de uso:")
print(f" Prompt tokens: {result['usage']['prompt_tokens']}")
print(f" Completion tokens: {result['usage']['completion_tokens']}")
print(f" Total tokens: {result['usage']['total_tokens']}")
print()
print("Estadísticas de costos (USD):")
print(f" Prompt cost: ${result['cost']['prompt_cost']:.6f}")
print(f" Completion cost: ${result['cost']['completion_cost']:.6f}")
print(f" Total cost: ${result['cost']['total_cost']:.6f}")
Algunos consejos prácticos para optimizar costos:
| Técnica | Cómo hacerlo | Proporción de ahorro |
|---|---|---|
| Elegir el modelo adecuado | Para tareas simples usa gpt-3.5-turbo, no gpt-4 | 90%+ |
| Limitar max_tokens | Establecer un límite razonable para evitar que la IA hable demasiado | Depende de la situación |
| Recortar el contexto | Conservar solo el historial de conversación necesario | 50%+ |
| El prompt debe ser conciso | El system prompt no debe ser demasiado largo | Según el caso |
| Caché de resultados | Para la misma pregunta, devolver directamente el resultado de la caché | Según el caso |
Estrategias de caché
Para preguntas repetidas, almacenar resultados en caché puede ahorrar mucho dinero:
Ejemplo
# Implementación simple de caché de respuestas
import hashlib
import json
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
class SimpleCache:
"""Caché simple en memoria"""
def __init__(self):
self.cache = {}
def _make_key(self, model: str, messages: list) -> str:
"""Genera la clave de caché según el contenido de la solicitud"""
# Serializar la información clave y obtener el hash
key_data = {
"model": model,
"messages": messages
}
key_str = json.dumps(key_data, sort_keys=True)
return hashlib.md5(key_str.encode()).hexdigest()
def get(self, model: str, messages: list):
"""Obtener caché"""
key = self._make_key(model, messages)
return self.cache.get(key)
def set(self, model: str, messages: list, value: str):
"""Establecer caché"""
key = self._make_key(model, messages)
self.cache[key] = value
# Función de chat con caché
cache = SimpleCache()
def chat_with_cache(model: str, messages: list):
# Primero consultar la caché
cached = cache.get(model, messages)
if cached:
print("(Caché encontrada, devolver directamente)")
return cached
# Si no se encuentra en caché, llamar a la API
response = client.chat.completions.create(
model=model,
messages=messages
)
reply = response.choices[0].message.content
# Almacenar en la caché
cache.set(model, messages, reply)
return reply
# Prueba
if __name__ == "__main__":
messages = [{"role": "user", "content": "¿Qué sitio web es EJEMPLO?"}]
print("Primera llamada...")
r1 = chat_with_cache("gpt-3.5-turbo", messages)
print(r1)
print()
print("Segunda llamada (misma pregunta)...")
r2 = chat_with_cache("gpt-3.5-turbo", messages)
print(r2)
Manejo de errores y mecanismos de reintento
Las solicitudes de red siempre pueden fallar, y la API no es una excepción. Un código robusto debe manejar diversas situaciones excepcionales.
Tipos de errores comunes
| Tipo de error | Código de estado HTTP | Causa | Forma de manejo |
|---|---|---|---|
| Error de autenticación | 401 | Clave de API incorrecta o expirada | Verificar la clave de API |
| Cuota insuficiente | 402 | La cuenta no tiene fondos | Recargar saldo o cambiar de cuenta |
| Límite excedido | 429 | Solicitudes demasiado rápidas o cuota agotada | Esperar un poco y volver a intentar |
| Error del servidor | 5xx | Problema en el servidor de IA | Reintentar |
Reintento con retroceso exponencial
Ante errores temporales (como 429, 5xx), la estrategia más común es el reintento con retroceso exponencial:
-
Primer fallo → esperar 1 segundo → reintentar
-
Segundo fallo → esperar 2 segundos → reintentar
-
Tercer fallo → esperar 4 segundos → reintentar
-
Cuarto fallo → esperar 8 segundos → reintentar
Cada vez, el tiempo de espera se duplica, dando al servicio la oportunidad de recuperarse.
Ejemplo
# Manejo de errores y reintentos con retroceso exponencial
import time
from openai import OpenAI, APIError, RateLimitError, APIConnectionError
client = OpenAI(api_key="your-api-key-here")
def chat_with_retry(
model: str,
messages: list,
max_retries: int = 3,
initial_wait: float = 1.0
):
"""Función de chat con mecanismo de reintentos"""
retries = 0
while retries <= max_retries:
try:
response = client.chat.completions.create(
model=model,
messages=messages
)
return {
"success": True,
"reply": response.choices[0].message.content
}
except RateLimitError as e:
# Error de límite de velocidad: esperar un poco y reintentar
retries += 1
if retries > max_retries:
return {
"success": False,
"error": f"Se agotaron los reintentos: {str(e)}"
}
wait_time = initial_wait * (2 ** (retries - 1))
print(f"Se activó el límite de velocidad, esperando {wait_time} segundos para reintentar...")
time.sleep(wait_time)
except APIConnectionError as e:
# Error de conexión de red: reintentar
retries += 1
if retries > max_retries:
return {
"success": False,
"error": f"Error de conexión de red: {str(e)}"
}
wait_time = initial_wait * (2 ** (retries - 1))
print(f"Error de red, esperando {wait_time} segundos para reintentar...")
time.sleep(wait_time)
except APIError as e:
# Error de API: reintentar según el caso
if e.status_code and 500 <= e.status_code < 600:
retries += 1
if retries > max_retries:
return {
"success": False,
"error": f"Error del servidor: {str(e)}"
}
wait_time = initial_wait * (2 ** (retries - 1))
print(f"Error del servidor, esperando {wait_time} segundos para reintentar...")
time.sleep(wait_time)
else:
# Errores que no sean 5xx, no reintentar
return {
"success": False,
"error": f"Error de API: {str(e)}"
}
except Exception as e:
# Otros errores, no reintentar
return {
"success": False,
"error": f"Error desconocido: {str(e)}"
}
# Ejemplo de uso
if __name__ == "__main__":
result = chat_with_retry(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Hola, EJEMPLO"}]
)
if result["success"]:
print("Éxito:", result["reply"])
else:
print("Fallo:", result["error"])
También puedes usar librerías existentes para simplificar la lógica de reintentos, como tenacity, instálala con el siguiente comando:
pip install tenacity
Ejemplo
# Usar la librería tenacity para simplificar la lógica de reintentos
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from openai import OpenAI, RateLimitError, APIError
client = OpenAI(api_key="your-api-key-here")
@retry(
stop=stop_after_attempt(3), # Reintentar como máximo 3 veces
wait=wait_exponential(multiplier=1, min=1, max=10), # Backoff exponencial: 1, 2, 4... máximo 10 segundos
retry=retry_if_exception_type((RateLimitError, APIError)) # Reintentar solo ante excepciones específicas
)
def chat_with_tenacity(model: str, messages: list):
"""Implementar reintentos con el decorador de tenacity"""
response = client.chat.completions.create(
model=model,
messages=messages
)
return response.choices[0].message.content
# Uso
try:
reply = chat_with_tenacity(
"gpt-3.5-turbo",
[{"role": "user", "content": "Presenta EJEMPLO"}]
)
print(reply)
except Exception as e:
print(f"Fallo final: {e}")
Proyecto práctico: herramienta de chat de IA en línea de comandos
Ahora integremos los conocimientos aprendidos anteriormente para crear una herramienta de chat completa de línea de comandos.
Ejemplo
# Robot de chat EJEMPLO AI - Herramienta completa de línea de comandos
import sys
import json
import os
from datetime import datetime
from openai import OpenAI
class EjemploChatBot:
"""Un robot de chat de línea de comandos con todas las funciones"""
def __init__(self, config_file: str = "config.json"):
# Cargar configuración
self.config = self._load_config(config_file)
self.client = OpenAI(api_key=self.config["api_key"])
# Estado de la conversación
self.messages = []
self.total_tokens = 0
self.total_cost = 0.0
# Inicializar el system prompt
self._init_system_prompt()
def _load_config(self, config_file: str) -> dict:
"""Cargar archivo de configuración"""
default_config = {
"api_key": "your-api-key-here",
"model": "gpt-3.5-turbo",
"system_prompt": "Eres un asistente AI servicial, con soporte técnico de EJEMPLO.",
"max_history": 20,
"stream": True,
"temperature": 0.7
}
if os.path.exists(config_file):
with open(config_file, "r", encoding="utf-8") as f:
user_config = json.load(f)
default_config.update(user_config)
return default_config
def _save_config(self, config_file: str = "config.json"):
"""Guardar archivo de configuración"""
with open(config_file, "w", encoding="utf-8") as f:
json.dump(self.config, f, indent=2, ensure_ascii=False)
def _init_system_prompt(self):
"""Inicializar el system prompt"""
self.messages = [
{
"role": "system",
"content": self.config["system_prompt"]
}
]
def _trim_history(self):
"""Recortar el historial de conversación"""
# Conservar el system prompt + los N mensajes de conversación más recientes
max_messages = self.config["max_history"]
if len(self.messages) > max_messages + 1:
self.messages = [self.messages[0]] + self.messages[-max_messages:]
def chat(self, user_input: str) -> str:
"""Enviar mensaje y obtener respuesta"""
# Añadir mensaje del usuario
self.messages.append({
"role": "user",
"content": user_input
})
# Recortar historial
self._trim_history()
if self.config["stream"]:
return self._chat_stream()
else:
return self._chat_normal()
def _chat_normal(self) -> str:
"""Modo normal (no streaming)"""
response = self.client.chat.completions.create(
model=self.config["model"],
messages=self.messages,
temperature=self.config["temperature"]
)
ai_reply = response.choices[0].message.content
# Contabilizar uso
if hasattr(response, "usage"):
self.total_tokens += response.usage.total_tokens
# Estimación simple de coste (precio de gpt-3.5-turbo)
self.total_cost += (response.usage.total_tokens / 1000) * 0.002
self.messages.append({
"role": "assistant",
"content": ai_reply
})
return ai_reply
def _chat_stream(self) -> str:
"""Modo streaming"""
response = self.client.chat.completions.create(
model=self.config["model"],
messages=self.messages,
temperature=self.config["temperature"],
stream=True
)
collected_chunks = []
print("AI:", end="", flush=True)
for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
print(content, end="", flush=True)
collected_chunks.append(content)
print()
ai_reply = "".join(collected_chunks)
self.messages.append({
"role": "assistant",
"content": ai_reply
})
# El conteo de tokens en modo streaming requiere procesamiento adicional, aquí se simplifica
# En proyectos reales se puede llamar a la interfaz usage o estimar
self.total_tokens += len(ai_reply) // 2 # Estimación aproximada
return ai_reply
def save_conversation(self, filename: str = None):
"""Guardar historial de conversación"""
if not filename:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"conversation_{timestamp}.json"
data = {
"model": self.config["model"],
"total_tokens": self.total_tokens,
"estimated_cost": self.total_cost,
"messages": self.messages,
"saved_at": datetime.now().isoformat()
}
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
return filename
def clear_history(self):
"""Borrar historial de conversación"""
self._init_system_prompt()
self.total_tokens = 0
self.total_cost = 0.0
def show_stats(self):
"""Mostrar información de estadísticas"""
print("\n" + "="*40)
print("Estadísticas de conversación")
print("="*40)
print(f"Modelo: {self.config['model']}")
print(f"Número de mensajes: {len(self.messages) - 1}")
print(f"Tokens totales: {self.total_tokens}")
print(f"Coste estimado: ${self.total_cost:.4f}")
print("="*40 + "\n")
def print_help():
"""Imprimir información de ayuda"""
print("\n" + "="*40)
print("Herramienta de chat EJEMPLO AI - Lista de comandos")
print("="*40)
print("/help - Mostrar ayuda")
print("/clear - Borrar historial de conversación")
print("/stats - Mostrar estadísticas")
print("/save - Guardar historial de conversación")
print("/model - Cambiar modelo")
print("/temp - Ajustar temperature")
print("/system - Modificar system prompt")
print("/quit - Salir del programa")
print("="*40 + "\n")
def main():
print("="*40)
print(" Herramienta de chat EJEMPLO AI")
print("="*40)
print("Escribe /help para ver comandos, escribe texto directamente para empezar a chatear"\n")
bot = EjemploChatBot()
while True:
try:
user_input = input("Tú:").strip()
if not user_input:
continue
# Procesar comandos
if user_input.startswith("/"):
cmd = user_input.lower()
if cmd in ["/quit", "/exit", "/q"]:
print("¡Adiós!")
break
elif cmd == "/help":
print_help()
elif cmd == "/clear":
bot.clear_history()
print("Historial de conversación borrado")
elif cmd == "/stats":
bot.show_stats()
elif cmd == "/save":
filename = bot.save_conversation()
print(f"Conversación guardada en: {filename}")
elif cmd.startswith("/model "):
model = user_input[7:].strip()
bot.config["model"] = model
bot._save_config()
print(f"Modelo cambiado a: {model}")
elif cmd.startswith("/temp "):
try:
temp = float(user_input[6:].strip())
if 0 <= temp <= 2:
bot.config["temperature"] = temp
bot._save_config()
print(f"Temperature establecido en: {temp}")
else:
print("Temperature debe estar entre 0 y 2")
except ValueError:
print("Por favor ingresa un número válido")
elif cmd.startswith("/system "):
system_prompt = user_input[8:].strip()
bot.config["system_prompt"] = system_prompt
bot.clear_history()
bot._save_config()
print("System prompt actualizado, conversación reiniciada")
else:
print("Comando desconocido, escribe /help para ver la ayuda")
else:
# Chat normal
if not bot.config["stream"]:
print("AI:", end="")
bot.chat(user_input)
print()
except KeyboardInterrupt:
print("\nEscribe /quit para salir, o continúa chateando")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()
Crea un archivo de configuración:
{
"api_key": "your-api-key-here",
"model": "gpt-3.5-turbo",
"system_prompt": "你是一个乐于助人的 AI 助手,由 EJEMPLO 提供技术支持。",
"max_history": 20,
"stream": true,
"temperature": 0.7
}
Ahora puedes ejecutar esta herramienta de chat:
python ejemplo_chatbot.py
Verás:
======================================== EJEMPLO AI 聊天工具 ======================================== 输入 /help 查看命令,直接输入文字开始聊天 你:你好 AI:你好!很高兴见到你。我是由 EJEMPLO 提供技术支持的 AI 助手,有什么可以帮你的吗? 你:/stats ======================================== 对话统计 ======================================== 模型:gpt-3.5-turbo 消息数:2 总 tokens:50 估算费用:$0.0001 ======================================== 你:/quit 再见!Otras extensiones