多模态输入处理
图像、音频、视频、PDF 等多模态内容的 API 调用方式。
什么是多模态?
多模态是指模型能够理解和处理多种类型的输入,不仅限于文本。现代大模型已经可以”看图”、“听音”、“读文档”。
多模态能力让 AI 应用场景大大扩展:
- 图像理解:识别图片内容、OCR 文字提取
- 文档分析:直接阅读 PDF、提取关键信息
- 音视频处理:转录、摘要、内容分析
多模态的价值:
| 传统方式 | 多模态方式 | 优势 |
|---|---|---|
| OCR + 文本处理 | 直接理解图像 | 保留上下文、理解布局 |
| PDF 解析 + 文本 | 直接阅读 PDF | 理解表格、图表 |
| 语音转文字 + 文本 | 直接理解音频 | 保留语气、情感 |
| 视频抽帧 + 图像 | 直接理解视频 | 理解动作、时序 |
多模态支持矩阵
| 类型 | OpenAI | Claude | Gemini | 说明 |
|---|---|---|---|---|
| 图像 | ✅ | ✅ | ✅ | 全部支持 |
| ❌ | ✅ | ✅ | OpenAI 需转换 | |
| 音频 | ✅ (Whisper) | ❌ | ✅ | Claude 不支持 |
| 视频 | ❌ | ❌ | ✅ | 仅 Gemini |
选择建议:
| 需求 | 推荐 |
|---|---|
| 图像理解 | 三家都可 |
| PDF 文档 | Claude、Gemini |
| 音频处理 | Gemini、OpenAI Whisper |
| 视频分析 | Gemini |
| 综合多模态 | Gemini |
图像处理
图像是最常用的多模态输入。三家厂商都支持图像理解,但输入格式略有不同。
输入方式
有三种方式传递图像:
- Base64 编码:将图像转为文本,适合小图、本地图片
- URL 链接:直接传递图片地址,适合网络图片
- 文件上传:先上传到云存储,再引用(Gemini)
Base64 方式最通用,但会增加请求体积(约增大 33%)。
flowchart LR
A[图像] --> B{输入方式}
B --> C[Base64 编码]
B --> D[URL 链接]
B --> E[文件上传]方式对比:
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Base64 | 通用、无需网络 | 请求体大 | 本地图片、小图 |
| URL | 请求体小 | 需要公开访问 | 网络图片 |
| 文件上传 | 支持大文件 | 需要额外步骤 | 大文件、重复使用 |
格式对比
| 厂商 | Base64 | URL |
|---|---|---|
| OpenAI | image_url.url: data:image/jpeg;base64,... | image_url.url: https://... |
| Claude | source.type: base64 | source.type: url |
| Gemini | inlineData.data | fileData.fileUri |
代码示例
import base64
# 读取图像并编码
with open("image.jpg", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
# OpenAI 格式
openai_image = {
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{b64}",
"detail": "high" # low/high/auto
}
}
# Claude 格式
claude_image = {
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": b64
}
}
# Gemini 格式
gemini_image = {
"inlineData": {
"mimeType": "image/jpeg",
"data": b64
}
}
图像限制:
| 厂商 | 最大大小 | 支持格式 | 每次最多 |
|---|---|---|---|
| OpenAI | 20MB | PNG, JPEG, GIF, WebP | 多张 |
| Claude | 20MB | PNG, JPEG, GIF, WebP | 多张 |
| Gemini | 20MB | PNG, JPEG, GIF, WebP | 多张 |
PDF 处理
PDF 是企业场景中最常见的文档格式。Claude 和 Gemini 原生支持 PDF 输入,可以直接”阅读”文档内容。
原生 PDF 支持的优势:
- 保留文档布局和格式
- 理解表格结构
- 识别图表和图像
- 处理多页文档
OpenAI 不直接支持 PDF,需要先转换:
- 转为图像(每页一张)
- 提取文本(丢失格式)
如果你的应用需要处理大量 PDF,建议优先选择 Claude 或 Gemini。
flowchart TD
A[PDF 文件] --> B{厂商}
B -->|Claude| C[直接支持]
B -->|Gemini| D[直接支持]
B -->|OpenAI| E[需转换]
E --> F[转图像]
E --> G[提取文本]Claude PDF
Claude 原生支持 PDF,可以理解文档结构:
import base64
with open("doc.pdf", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
message = {
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": b64
}
},
{"type": "text", "text": "总结这份文档的要点"}
]
}
Gemini PDF
message = {
"role": "user",
"parts": [
{"inlineData": {"mimeType": "application/pdf", "data": b64}},
{"text": "总结这份文档"}
]
}
音频处理
音频处理主要用于语音转文字、会议记录、播客摘要等场景。
Gemini 原生支持
Gemini 可以直接理解音频内容,支持多种格式。这是目前最便捷的方案。
# 支持格式: mp3, wav, aac, flac, ogg
message = {
"role": "user",
"parts": [
{"inlineData": {"mimeType": "audio/mp3", "data": audio_b64}},
{"text": "转录这段音频"}
]
}
OpenAI Whisper
OpenAI 通过独立的 Whisper API 提供语音转文字功能,准确率很高,支持多语言。
# 语音转文字(独立 API)
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=open("audio.mp3", "rb")
)
OpenAI Realtime API (音频对话)
GPT-4o 支持通过 WebSocket 进行实时音频对话,无需先转录为文本。这对于低延迟语音助手至关重要。
// 需使用 WebSocket 连接 wss://api.openai.com/v1/realtime
// 详见 06-传输协议对比.md
视频处理
视频理解是 Gemini 的独特优势。它可以分析视频内容、提取关键帧、生成摘要。
由于视频文件通常较大,需要先上传到 Google Cloud Storage,再通过 URI 引用。Gemini 1.5 Pro 支持最长 2 小时的视频。
flowchart LR
A[视频] --> B[上传到 GCS]
B --> C[Gemini API]
C --> D[分析结果]Gemini 视频分析
# 需要先上传到 Google Cloud Storage
message = {
"role": "user",
"parts": [
{"fileData": {"mimeType": "video/mp4", "fileUri": "gs://bucket/video.mp4"}},
{"text": "描述视频内容"}
]
}
统一处理方案
flowchart TD
A[多模态输入] --> B{文件类型}
B -->|图像| C[统一转 Base64]
B -->|PDF| D{厂商支持?}
B -->|音频| E{厂商支持?}
B -->|视频| F[仅 Gemini]
D -->|是| G[直接发送]
D -->|否| H[转图像/文本]
E -->|是| I[直接发送]
E -->|否| J[Whisper 转文字]工具函数
def prepare_image(path):
"""统一图像处理"""
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode()
def get_mime_type(path):
"""获取 MIME 类型"""
ext = path.split(".")[-1].lower()
return {
"jpg": "image/jpeg", "jpeg": "image/jpeg",
"png": "image/png", "gif": "image/gif",
"pdf": "application/pdf",
"mp3": "audio/mp3", "wav": "audio/wav",
"mp4": "video/mp4"
}.get(ext, "application/octet-stream")
限制与注意
| 厂商 | 图像大小 | 图像数量 | 特殊限制 |
|---|---|---|---|
| OpenAI | 20MB | 多张 | - |
| Claude | 5MB | 20张 | PDF < 100页 |
| Gemini | 20MB | 多张 | 视频 < 2小时 |
图像最佳实践
分辨率选择
图像分辨率直接影响 Token 消耗和识别效果。需要在成本和质量间平衡。
| 场景 | 建议分辨率 | 说明 |
|---|---|---|
| 文字识别 OCR | 高分辨率 | 需要清晰细节 |
| 图片分类 | 低分辨率 | 整体特征即可 |
| 图表分析 | 中等分辨率 | 需要看清数字 |
| 人脸识别 | 中等分辨率 | 面部特征 |
图像预处理
from PIL import Image
def optimize_image(path, max_size=1024):
"""优化图像尺寸,减少 Token 消耗"""
img = Image.open(path)
# 等比缩放
ratio = min(max_size / img.width, max_size / img.height)
if ratio < 1:
new_size = (int(img.width * ratio), int(img.height * ratio))
img = img.resize(new_size, Image.LANCZOS)
# 转换格式(JPEG 更小)
if img.mode == 'RGBA':
img = img.convert('RGB')
return img
多图像策略
当需要分析多张图像时:
flowchart TD
A[多张图像] --> B{数量}
B -->|少量 < 5| C[一次请求]
B -->|中等 5-20| D[分批请求]
B -->|大量 > 20| E[并行处理]
C --> F[合并分析]
D --> F
E --> F常见问题
Q: 图像识别不准确怎么办?
| 问题 | 解决方案 |
|---|---|
| 图像模糊 | 提高分辨率、增强清晰度 |
| 对比度低 | 预处理增强对比度 |
| 目标太小 | 裁剪关键区域 |
| 缺少上下文 | 在 Prompt 中说明背景 |
# 图像增强示例
from PIL import Image, ImageEnhance
def enhance_image(img):
# 增强对比度
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(1.5)
# 增强锐度
enhancer = ImageEnhance.Sharpness(img)
img = enhancer.enhance(2.0)
return img
Q: PDF 页数太多怎么处理?
flowchart TD
A[大型 PDF] --> B{页数}
B -->|< 50 页| C[直接处理]
B -->|50-200 页| D[分批处理]
B -->|> 200 页| E[提取关键页]
D --> F[每批 30 页]
E --> G[目录/摘要页]处理策略:
- 分批处理:每批 20-30 页,合并结果
- 提取关键页:目录、摘要、结论
- OCR + 文本:先提取文本,再分析
- 向量检索:建立索引,按需检索
Q: 视频太长怎么办?
- 提取关键帧:每 N 秒提取一帧
- 分段处理:每段 5-10 分钟
- 先摘要后详细:先生成整体摘要,再深入分析
- 音频分离:单独处理音频转录
# 视频关键帧提取示例
import cv2
def extract_keyframes(video_path, interval_seconds=10):
"""每隔 N 秒提取一帧"""
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
interval_frames = int(fps * interval_seconds)
frames = []
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
if frame_count % interval_frames == 0:
frames.append(frame)
frame_count += 1
cap.release()
return frames
Q: 多模态请求太慢?
| 优化方法 | 效果 |
|---|---|
| 压缩图像 | 减少传输时间 |
| 使用 URL | 避免 Base64 编码开销 |
| 并行请求 | 多图像并行处理 |
| 预处理 | 提前准备数据 |
多模态应用场景
1. 智能文档处理
async def process_document(pdf_path):
"""智能文档处理流程"""
# 1. 读取 PDF
with open(pdf_path, "rb") as f:
pdf_b64 = base64.b64encode(f.read()).decode()
# 2. 提取结构化信息
response = await client.messages.create(
model="claude-sonnet-4-20250514",
messages=[{
"role": "user",
"content": [
{"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": pdf_b64}},
{"type": "text", "text": """
分析这份文档,提取以下信息(JSON 格式):
- title: 文档标题
- date: 日期
- summary: 摘要(100字内)
- key_points: 关键要点(列表)
- tables: 表格数据(如有)
"""}
]
}]
)
return response.content[0].text
2. 商品图像分析
def analyze_product_image(image_path):
"""电商商品图像分析"""
b64 = prepare_image(image_path)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}},
{"type": "text", "text": """
分析这张商品图片,提供:
1. 商品类别
2. 主要特征(颜色、材质、风格)
3. 适合的使用场景
4. 建议的标签(用于搜索)
5. 图片质量评估
"""}
]
}]
)
return response.choices[0].message.content
3. 会议记录处理
async def process_meeting_recording(audio_path):
"""会议录音处理"""
# 1. 语音转文字
with open(audio_path, "rb") as f:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=f,
response_format="verbose_json"
)
# 2. 生成会议纪要
summary = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": f"""
根据以下会议转录,生成会议纪要:
{transcript.text}
请包含:
1. 会议主题
2. 参会人员(如能识别)
3. 讨论要点
4. 决议事项
5. 待办事项(Action Items)
"""
}]
)
return {
"transcript": transcript.text,
"summary": summary.choices[0].message.content
}