Ir al contenido

Multimodal

AI-Lib soporta entradas multimodales — texto combinado con imágenes — a través de la misma API unificada.

CapabilityDirectionProviders
Vision (imágenes)InputOpenAI, Anthropic, Gemini, Qwen, DeepSeek
Generación de imágenesOutputOpenAI (DALL-E), algunos proveedores
Entrada de audioInputGemini, Qwen (modo omni)
Salida de audioOutputQwen (modo omni), algunos proveedores
Entrada de videoInputGemini
Modo OmniInput + OutputQwen (texto y audio al unísono)
use ai_lib_rust::{AiClient, Message, ContentBlock};
let client = AiClient::new("openai/gpt-4o").await?;
let message = Message::user_with_content(vec![
ContentBlock::Text("What's in this image?".into()),
ContentBlock::ImageUrl {
url: "https://example.com/photo.jpg".into(),
},
]);
let response = client.chat()
.messages(vec![message])
.execute()
.await?;
println!("{}", response.content);
from ai_lib_python import AiClient, Message, ContentBlock
client = await AiClient.create("openai/gpt-4o")
message = Message.user_with_content([
ContentBlock.text("What's in this image?"),
ContentBlock.image_url("https://example.com/photo.jpg"),
])
response = await client.chat() \
.messages([message]) \
.execute()
print(response.content)
import { AiClient, Message, ContentBlock } from '@hiddenpath/ai-lib-ts';
const client = await AiClient.new('openai/gpt-4o');
const message = Message.userWithContent([
ContentBlock.text("What's in this image?"),
ContentBlock.imageUrl('https://example.com/photo.jpg'),
]);
const response = await client
.chat()
.messages([message])
.execute();
console.log(response.content);

Para imágenes locales, use codificación base64:

let image_data = std::fs::read("photo.jpg")?;
let base64 = base64::engine::general_purpose::STANDARD.encode(&image_data);
let message = Message::user_with_content(vec![
ContentBlock::Text("Describe this".into()),
ContentBlock::ImageBase64 {
data: base64,
media_type: "image/jpeg".into(),
},
]);
import base64
with open("photo.jpg", "rb") as f:
image_data = base64.b64encode(f.read()).decode()
message = Message.user_with_content([
ContentBlock.text("Describe this"),
ContentBlock.image_base64(image_data, "image/jpeg"),
])
import { readFileSync } from 'fs';
const imageBuffer = readFileSync('photo.jpg');
const imageData = imageBuffer.toString('base64');
const message = Message.userWithContent([
ContentBlock.text('Describe this'),
ContentBlock.imageBase64(imageData, 'image/jpeg'),
]);

El protocolo V2 proporciona el módulo MultimodalCapabilities para validar el contenido contra las declaraciones del proveedor antes de enviar solicitudes.

El tiempo de ejecución detecta automáticamente los modales en los bloques de contenido:

use ai_lib_rust::multimodal::{detect_modalities, Modality};
let modalities = detect_modalities(&content_blocks);
// Devuelve: {Text, Image} o {Text, Audio, Video} etc.
from ai_lib_python.multimodal import detect_modalities, Modality
modalities = detect_modalities(content_blocks)
# Devuelve: {Modality.TEXT, Modality.IMAGE}
// TypeScript
import { detectModalities, Modality } from '@hiddenpath/ai-lib-ts/multimodal';
const modalities = detectModalities(contentBlocks);
// Devuelve: Set { Modality.TEXT, Modality.IMAGE }

El tiempo de ejecución valida el formato contra lo que soporta el proveedor:

use ai_lib_rust::multimodal::MultimodalCapabilities;
let caps = MultimodalCapabilities::from_config(&manifest.multimodal);
assert!(caps.validate_image_format("png"));
assert!(caps.validate_audio_format("wav"));
from ai_lib_python.multimodal import MultimodalCapabilities
caps = MultimodalCapabilities.from_config(manifest_multimodal)
assert caps.validate_image_format("png")
assert caps.validate_audio_format("wav")
// TypeScript
import { MultimodalCapabilities } from '@hiddenpath/ai-lib-ts/multimodal';
const caps = MultimodalCapabilities.fromConfig(manifestMultimodal);
console.assert(caps.validateImageFormat('png'));
console.assert(caps.validateAudioFormat('wav'));

Valida que el proveedor soporte todos los modales en el contenido antes de enviar la solicitud:

use ai_lib_rust::multimodal::validate_content_modalities;
match validate_content_modalities(&blocks, &caps) {
Ok(()) => { /* todos los modales son soportados */ }
Err(unsupported) => {
eprintln!("El proveedor no soporta: {:?}", unsupported);
}
}
from ai_lib_python.multimodal import validate_content_modalities
# Validar bloques de contenido contra las capacidades del proveedor
// TypeScript
import { validateContentModalities } from '@hiddenpath/ai-lib-ts/multimodal';
try {
validateContentModalities(blocks, caps);
// todos los modales son soportados
} catch (unsupported) {
console.error(`El proveedor no soporta: ${unsupported}`);
}
  1. El tiempo de ejecución construye un mensaje multimodal con bloques de contenido mixtos
  2. Validación V2: MultimodalCapabilities comprueba que todos los modales de contenido sean soportados por el proveedor
  3. El manifiesto del protocolo mapea los bloques de contenido al formato del proveedor
  4. Diferentes proveedores usan estructuras diferentes:
    • OpenAI: Array content con objetos type: "image_url"
    • Anthropic: Array content con objetos type: "image"
    • Gemini: Array parts con objetos inline_data (soporta parts de video)
  5. El protocolo maneja todas las diferencias de formato automáticamente

El manifiesto V2 declara explícitamente las características multimodales para cada proveedor:

ProveedorImage InAudio InVideo InImage OutAudio OutOmni
OpenAI✅ png, jpg, gif, webp
Anthropic✅ png, jpg, gif, webp
Gemini✅ png, jpg, gif, webp✅ wav, mp3, flac✅ mp4, avi
Qwen✅ png, jpg✅ wav, mp3
DeepSeek✅ png, jpg

Por favor, revise las secciones multimodal.input y multimodal.output en los manifiestos de los proveedores V2 para la declaración completa.