AWS Bedrock — un cliente genérico de AWS, y el cuerpo en JSON crudo:
bedrock = boto3.client(service_name='bedrock-runtime', region_name='us-east-1')
body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1024,
"messages": [{"role": "user", "content": prompt}]
})
response = bedrock.invoke_model(modelId='anthropic.claude-...', body=body)
texto = json.loads(response['body'].read())['content'][0]['text']
Azure OpenAI — el SDK de OpenAI, con otra clase y un endpoint propio:
client = AzureOpenAI(api_key=..., api_version="2024-02-15-preview",
azure_endpoint="https://<recurso>.openai.azure.com/")
response = client.chat.completions.create(
model=DEPLOYMENT_NAME, # ojo: NO es el nombre del modelo
messages=messages
)
texto = response.choices[0].message.content
Vertex AI — inicialización global con proyecto y región, y objetos propios:
vertexai.init(project=PROJECT_ID, location="us-central1")
model = GenerativeModel("gemini-...")
response = model.generate_content(prompt, generation_config={...})
texto = response.text
| Nube | La trampa | Cómo se manifiesta |
|---|---|---|
| Bedrock | El cuerpo lo define el proveedor del modelo, no AWS: de ahí anthropic_version | Cambiar de Claude a Llama exige reescribir el JSON entero, no solo el modelId |
| Azure OpenAI | model= es el nombre de tu deployment, no del modelo | Un despliegue que funciona en desarrollo falla en producción: los nombres de deployment no coinciden |
| Vertex AI | Proyecto y región viven en un init() global, no en la llamada | Cambiar de región es tocar la inicialización; un modelo puede no existir en tu región |
La primera es la que más sorprende. Bedrock parece una API de AWS y en realidad es un
sobre: por fuera es invoke_model, por dentro va el formato nativo del proveedor.
Por eso el cuerpo lleva una versión con nombre de Anthropic dentro de una llamada de boto3. Es
coherente —permite exponer modelos de terceros sin traducirlos— y significa que «cambiar de modelo
en Bedrock» no es cambiar una cadena.
La segunda es la que más tiempo cuesta depurar, porque el error no dice lo que pasa: pides un
deployment que no existe y recibes un mensaje que suena a modelo no encontrado. Que la clave del
SDK se llame model y contenga otra cosa es una trampa de diseño heredada de mantener
compatibilidad con el SDK de OpenAI.
Las tres ofrecen las dos vías, y la diferencia es la misma que ya aparecía entre las dos puertas de los modelos de Google en el Módulo 8:
| Clave estática | Identidad de la nube | |
|---|---|---|
| AWS | Claves de acceso en el entorno | Rol de IAM asumido por el recurso |
| Azure | api_key | Azure AD / Entra ID, con proveedor de token |
| API key (solo en la puerta de AI Studio) | Cuenta de servicio o credenciales por defecto | |
| Qué implica | Un secreto que rotar y que se filtra en un commit | Nada que guardar; permisos revocables al instante |
La segunda columna es la que se usa en producción, y no por purismo: una credencial que no existe como cadena no se puede filtrar, y los permisos se retiran desde la consola sin desplegar nada. El coste es que el código deja de funcionar fuera de la nube — lo cual, en un servicio desplegado ahí, no es un problema.
"anthropic_version": "bedrock-2023-05-31" en el cuerpo de Bedrock,
api_version="2024-02-15-preview" en el cliente de Azure — nótese el
preview — y los identificadores de modelo con su fecha de release
(claude-3-sonnet-20240229-v1:0, gemini-1.5-pro-001).
¿Qué pasa cuando una versión de API en preview deja de estarlo, y sigue siendo esa la que
debes pasar? Y una pregunta de método: ¿por qué la guía fija esas versiones a mano en vez de
dejar que el SDK use la actual? Merece la pena entender qué se rompe al subirlas, porque es
exactamente el tipo de cadena que nadie toca hasta que falla.
Implementa preguntar(prompt) -> str contra dos de las tres nubes, con la misma
firma y el mismo comportamiento. No hace falta que ambas funcionen: basta con escribirlas.
Lo que buscas es la lista de lo que no se puede unificar detrás de esa firma: el formato del cuerpo, el significado del identificador, dónde viven proyecto y región, cómo se pide la credencial. Esa lista es, literalmente, el coste de portar tu código el día que alguien proponga cambiar de proveedor.