Inicio / Artículos

API de Gemini en Python: El mismo bucle sin estado con roles del modelo y objetos de chat.

Llamar a Gemini desde Python con el SDK google-genai: contenido y partes, system_instruction, uso de tokens y un objeto de chat que registra el historial en el cliente.

Editor: REACTAPP.TOP4 min de lectura892 palabras

Fuentes: Part 4 — Call the Gemini API in Python (user / model, same loop)

Después de OpenAI y Claude, Gemini de Google es el tercer proveedor que sigue este mismo patrón: un endpoint sin estado, una conversación etiquetada por rol y el historial completo enviado en cada llamada. Gemini añade además una particularidad agradable en su nomenclatura.

Cambios de nombre, no rediseño

La estructura de las conversaciones en Gemini es similar a la de OpenAI y Claude, con la excepción de dos cambios de nombre. El rol del asistente ahora se denomina model. Este término resulta quizás más preciso, ya que “asistente” sugiere una personalidad mientras que model indica simplemente que el texto proviene de un modelo. Ocupa el mismo lugar en la lista. La instrucción del sistema pasa a llamarse system_instruction, y se transmite mediante un objeto de configuración en lugar de incluirla en la lista de mensajes. Esto representa una versión avanzada de la idea de “sistema separado” utilizada por Claude.

La lista de mensajes se accede mediante contents. Cada turno en ella contiene parts, ya que Gemini maneja texto, imágenes y audio de forma nativa. En los chats de texto plano no se muestra nada de eso: se ingresan cadenas y sale resp.text.

Una advertencia sobre las bibliotecas antes de cualquier código. A lo largo de los años, Google ha lanzado varios paquetes en Python, y los tutoriales antiguos están repletos de importaciones obsoletas como google-generativeai y wrappers de la época de Bard. El SDK oficial actual es google-genai, que se importa con from google import genai, y es el que se utiliza aquí.

Configuración y un único turno

Instálelo con pip install google-genai, cree una clave en Google AI Studio y guárdela como GEMINI_API_KEY. El cliente obtiene la clave del entorno, por lo que nunca aparece en el código.

# current official SDK: pip install google-genai
from google import genai
from google.genai import types

client = genai.Client()  # key from env

resp = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Why does Gemini name the reply "
             "role 'model', not 'assistant'?",
    config=types.GenerateContentConfig(
        system_instruction="Be concise.",
        temperature=0,
    ),
)
print(resp.text)

Frente a los dos proveedores anteriores, messages ahora es contents, y una sola jugada puede ser simplemente una cadena de texto. La instrucción del sistema se encuentra en GenerateContentConfig. La temperatura vuelve a ser un campo de configuración normal, algo que la versión actual del SDK de Claude había eliminado. La respuesta es simplemente resp.text, y los recuentos de tokens se encuentran en resp.usage_metadata como prompt_token_count y candidates_token_count, las mismas métricas pero con nombres propios de Google. Siempre regístrelas.

Bucle de historial gestionado

Es posible portar directamente su propia función ask(): guarde las turnos de user y model en una lista, añada cada intercambio y pase nuevamente contents= en cada ocasión. Funciona. Sin embargo, el SDK incluye una comodidad que los clientes de OpenAI y Anthropic no tienen por defecto: un objeto de chat que se encarga de agregar los datos.

chat = client.chats.create(
    model="gemini-2.5-flash",
    config=types.GenerateContentConfig(
        system_instruction="Be concise.",
    ),
)

r1 = chat.send_message(
    "Define a context window."
)
print(r1.text)

r2 = chat.send_message(
    "Now for a five-year-old."
)
print(r2.text)

for turn in chat.get_history():
    part = turn.parts[0].text[:40]
    print(turn.role, "->", part)

La respuesta se da en el contexto, ya que el objeto de chat reproduce silenciosamente el intercambio anterior, algo que haría una función implementada a mano. Si recorres get_history() al final, verás turnos alternados de user y model, que es exactamente la lista que se envió en la última solicitud. El servidor no recuerda nada. El objeto de chat guarda lo escrito en el cliente, por lo que los tokens de entrada siguen acumulándose en cada turno y las conversaciones largas cuestan más por llamada.

Una cosa no ha cambiado: el servicio detrás del SDK no recuerda nada entre solicitudes.

La comodidad tiene un precio, y eso es importante más adelante con los frameworks. Una historia gestionada implica menos código y fewer errores, hasta el momento en que debas eliminar versiones antiguas, resumirlas o insertar documentos recuperados en medio de una conversación. Entonces querrás volver a la lista simple. LangChain se encuentra en el mismo punto de esta escala, pero un nivel por encima. Acostúmbrate tanto a la lista mantenida manualmente como al objeto gestionado, ya que ninguno de los dos te limitará.

Ejecutar el ejemplo

pip install -r requirements.txt
export GEMINI_API_KEY="AIza..."
python examples/part04_gemini.py

El script aborda tres aspectos en orden: una sola ronda de conversación, el bucle de lista manual para confirmar que es equivalente, y el chat gestionado con su historial impreso. Se registra el conteo de tokens después de cada llamada. Si no se establece ninguna clave, se detiene inmediatamente con un mensaje claro. Dado que las llamadas son en tiempo real y se facturan, no se debe ejecutar en CI.

Tres proveedores, una misma estructura

Una comparación rápida de los tres. OpenAI trata system como un mensaje y deja el historial en manos del usuario. Claude convierte system en un parámetro separado, exige max_tokens y también deja el historial al usuario. Gemini incluye system_instruction en la configuración, denomina al asistente model y conservará el historial si se permite. Los tres utilizan el mismo bucle sin estado: enviar toda la conversación, recibir una respuesta, añadirla y repetir el proceso.

Esa es la razón por la cual los frameworks multi-proveedor pueden mantenerse ligeros, y por qué cambiar de proveedor no tiene por qué ser algo intimidante. La migración consiste en un mapeo de nombres, no en una reescritura.

Lecturas relacionadas

  • Portar un bucle de chat de OpenAI a Claude en Python: una página de cambios — Mover un bucle de mensajes sin estado a la Messages API de Anthropic: el parámetro del sistema de nivel superior, los max_tokens requeridos, los bloques de contenido y la alternancia estricta de roles.