多模态应用开发:文本+图片+语音
截图了一段报错信息,想让AI帮你分析,但只能手动把错误信息打出来拍了一张产品图,想让AI生成描述文案,但只能文字描述图片内容想让AI听一段录音并总结要点,但没有合适的工具多模态AI解决的就是这些问题——让AI同时理解文本、图片、语音,不再局限于"文字进、文字出"。模态能力代表API文本理解+生成图片看图说话、图生文语音识别+合成图片理解:让AI"看懂"图片语音识别:把音频转成文字语音合成:把文字转
·
📚 本文属于《AI开发实战》系列第7篇
- ✅ 已完成:系列一第1-6篇
- 🔄 进行中:系列一第7篇 ← 当前
- 📋 待开始:系列一第8篇
📌 前置知识:建议先阅读 第1篇、第2篇、第3篇、第4篇、第5篇、第6篇
一、前言:为什么多模态是AI的下一站
你有没有遇到过这些场景:
- 截图了一段报错信息,想让AI帮你分析,但只能手动把错误信息打出来
- 拍了一张产品图,想让AI生成描述文案,但只能文字描述图片内容
- 想让AI听一段录音并总结要点,但没有合适的工具
多模态AI 解决的就是这些问题——让AI同时理解文本、图片、语音,不再局限于"文字进、文字出"。
| 模态 | 能力 | 代表API |
|---|---|---|
| 文本 | 理解+生成 | GPT-4o、Claude 3.5 |
| 图片 | 看图说话、图生文 | GPT-4o、Claude 3.5 |
| 语音 | 识别+合成 | Whisper、TTS |
本文会讲什么:
- 图片理解:让AI"看懂"图片
- 语音识别:把音频转成文字
- 语音合成:把文字转成语音
- 综合实战:打造一个多模态AI助手
二、环境准备
2.1 依赖安装
pip install openai>=1.12.0 anthropic>=0.21.0 python-multipart aiofiles
2.2 API说明
| 服务 | API | 说明 |
|---|---|---|
| OpenAI | GPT-4o | 支持图片输入 |
| Anthropic | Claude 3.5 | 支持图片输入 |
| OpenAI | Whisper | 语音转文字 |
| OpenAI | TTS | 文字转语音 |
三、图片理解:让AI看懂图片
3.1 GPT-4o 图片理解
GPT-4o 支持直接传入图片,可以是URL或base64编码。
3.1.1 从URL读取图片
import os
from openai import OpenAI
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def describe_image_from_url(image_url: str, prompt: str = "描述这张图片") -> str:
"""根据URL分析图片"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {"url": image_url}
}
]
}
]
)
return response.choices[0].message.content
# 示例:分析一张技术架构图
result = describe_image_from_url(
"https://example.com/architecture.png",
"这是一个系统架构图,帮我分析优缺点"
)
print(result)
3.1.2 从本地文件读取(base64)
import base64
from openai import OpenAI
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def describe_image_from_file(image_path: str, prompt: str = "描述这张图片") -> str:
"""分析本地图片文件"""
# 读取图片并转为base64
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{image_data}"
}
}
]
}
]
)
return response.choices[0].message.content
# 分析本地截图
result = describe_image_from_file(
"screenshot.png",
"这是一个错误截图,帮我分析可能的原因"
)
print(result)
3.1.3 同时分析多张图片
def compare_images(image_urls: list, prompt: str = "比较这些图片的异同") -> str:
"""同时分析多张图片"""
content = [{"type": "text", "text": prompt}]
for url in image_urls:
content.append({
"type": "image_url",
"image_url": {"url": url}
})
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": content}]
)
return response.choices[0].message.content
# 比较两张设计稿
result = compare_images([
"https://example.com/design-v1.png",
"https://example.com/design-v2.png"
], "比较这两个UI设计稿的布局差异")
3.2 Claude 图片理解
Claude 3.5 Sonnet 也支持图片理解,语法略有不同。
from anthropic import Anthropic
client = Anthropic()
def describe_image_claude(image_path: str, prompt: str = "描述这张图片") -> str:
"""用Claude分析本地图片"""
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data
}
},
{
"type": "text",
"text": prompt
}
]
}
]
)
return message.content[0].text
# 分析截图
result = describe_image_claude("error_screen.png", "这是一个bug截图,帮我定位问题")
3.3 实际应用:AI代码截图审查
def review_code_screenshot(image_path: str) -> dict:
"""分析代码截图,返回审查结果"""
prompt = """请审查这张代码截图,完成以下任务:
1. 识别代码语言
2. 找出潜在的bug或问题
3. 给出改进建议
以JSON格式返回结果,包含 keys: language, issues[], suggestions[]"""
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_data}"}
}
]
}
],
response_format={"type": "json_object"}
)
import json
return json.loads(response.choices[0].message.content)
# 审查代码截图
result = review_code_screenshot("code_review.png")
print(f"语言: {result['language']}")
print(f"问题: {result['issues']}")
四、语音识别:让AI听懂音频
4.1 Whisper 语音转文字
OpenAI的Whisper是当前最好的开源语音识别模型之一。
4.1.1 基础用法:音频文件转文字
import os
from openai import OpenAI
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def transcribe_audio(audio_path: str) -> str:
"""将音频文件转录为文字"""
with open(audio_path, "rb") as f:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=f,
response_format="text" # 可选: text, json, srt, verbose_json, vtt
)
return transcript
# 转录会议录音
result = transcribe_audio("meeting.mp3")
print(result)
4.1.2 带说话人分离(后处理)
def transcribe_with_timestamps(audio_path: str) -> list:
"""转录并保留时间戳"""
with open(audio_path, "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-1",
file=f,
response_format="verbose_json",
timestamp_granularities=["segment"]
)
segments = []
for seg in result.segments:
segments.append({
"start": seg.start,
"end": seg.end,
"text": seg.text.strip()
})
return segments
# 打印带时间戳的转录
segments = transcribe_with_timestamps("lecture.mp3")
for seg in segments:
print(f"[{seg['start']:.1f}s - {seg['end']:.1f}s] {seg['text']}")
4.1.3 指定语言 + 翻译
def transcribe_with_prompt(audio_path: str, prompt: str = "") -> str:
"""使用提示词改善转录质量
prompt可以指定:
- 音频语言
- 专有名词
- 上下文信息
"""
with open(audio_path, "rb") as f:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language="zh", # 指定语言,空白则自动检测
prompt=prompt, # 可选,帮助模型理解上下文
response_format="text"
)
return transcript
# 转录中文音频,提示专有名词
result = transcribe_with_prompt(
"tech_talk.mp3",
prompt="涉及以下技术名词:LangChain、OpenAI、Claude、Vector Database"
)
4.2 实际应用:会议纪要生成
def meeting_minutes_generator(audio_path: str) -> dict:
"""从会议录音生成会议纪要"""
# 第一步:转录
transcript = transcribe_audio(audio_path)
# 第二步:让AI总结
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": "你是一个会议纪要助手。请根据会议记录,生成结构化的会议纪要,包括:参会人员、讨论要点、决议事项、下一步行动。"
},
{
"role": "user",
"content": f"请为以下会议记录生成纪要:\n\n{transcript}"
}
],
response_format={"type": "json_object"}
)
import json
return json.loads(response.choices[0].message.content)
# 生成会议纪要
minutes = meeting_minutes_generator("weekly_meeting.mp3")
print(f"参会人员: {minutes['participants']}")
print(f"讨论要点: {minutes['discussion_points']}")
print(f"决议: {minutes['decisions']}")
print(f"下一步: {minutes['action_items']}")
五、语音合成:让AI开口说话
5.1 TTS 文字转语音
import os
from openai import OpenAI
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def text_to_speech(
text: str,
output_path: str = "output.mp3",
voice: str = "alloy", # alloy, echo, fable, onyx, nova, shimmer
model: str = "tts-1" # tts-1 或 tts-1-hd(高清)
) -> str:
"""将文字转为语音"""
response = client.audio.speech.create(
model=model,
voice=voice,
input=text
)
response.write_to_file(output_path) # 注意:新版本SDK用 write_to_file
return output_path
# 基础用法
text_to_speech("你好,这是一个语音合成的测试。")
# 使用不同音色
text_to_speech(
"大家好,欢迎收听今天的AI技术播客",
output_path="podcast_intro.mp3",
voice="nova" # 更温暖的音色
)
5.2 语音角色扮演
def ai_voice_assistant(text: str, style: str = "professional") -> str:
"""根据场景调整语音风格
style选项:
- professional: 专业正式
- friendly: 友好轻松
- calm: 冷静沉稳
"""
voice_map = {
"professional": "alloy", # 中性专业
"friendly": "onyx", # 温暖友好
"calm": "echo" # 沉稳平和
}
voice = voice_map.get(style, "alloy")
output_path = f"response_{style}.mp3"
return text_to_speech(text, output_path, voice=voice)
# 专业播报
ai_voice_assistant(
"今日股价上涨3.5%,成交量放大至500万股",
style="professional"
)
# 轻松对话
ai_voice_assistant(
"太好了!这个功能终于上线了!",
style="friendly"
)
5.3 SSML 高级控制(可选)
TTS支持SSML标记,可以更精细地控制停顿、音调等:
def text_to_speech_with_ssml(text: str, output_path: str = "output.mp3") -> str:
"""使用SSML精细控制语音"""
ssml = f"""<speak>
<break time="500ms"/>
{text}
<break time="300ms"/>
播报完毕。
</speak>"""
response = client.audio.speech.create(
model="tts-1",
voice="alloy",
input=ssml,
response_format="mp3"
)
response.write_to_file(output_path)
return output_path
六、综合实战:打造多模态AI助手
6.1 项目需求
我们来实现一个多模态AI助手,支持:
- 文本对话
- 图片分析
- 语音输入(语音转文字 → AI处理 → 语音回复)
- 语音播报
6.2 核心代码
import os
import base64
from openai import OpenAI
from anthropic import Anthropic
client_openai = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
client_anthropic = Anthropic()
class MultimodalAssistant:
def __init__(self):
self.model = "gpt-4o" # 支持多模态的主力模型
def chat(self, message: str) -> str:
"""文本对话"""
response = client_openai.chat.completions.create(
model=self.model,
messages=[{"role": "user", "content": message}]
)
return response.choices[0].message.content
def analyze_image(self, image_path: str, question: str = "描述这张图片") -> str:
"""分析图片"""
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
response = client_openai.chat.completions.create(
model=self.model,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": question},
{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_data}"}
}
]
}
]
)
return response.choices[0].message.content
def speech_to_text(self, audio_path: str) -> str:
"""语音转文字"""
with open(audio_path, "rb") as f:
transcript = client_openai.audio.transcriptions.create(
model="whisper-1",
file=f,
response_format="text"
)
return transcript
def text_to_speech(self, text: str, output_path: str = "response.mp3") -> str:
"""文字转语音"""
response = client_openai.audio.speech.create(
model="tts-1",
voice="alloy",
input=text
)
response.write_to_file(output_path)
return output_path
def voice_interaction(self, audio_path: str) -> tuple[str, str]:
"""完整语音交互:语音输入 → AI处理 → 语音输出"""
# 1. 语音转文字
user_text = self.speech_to_text(audio_path)
print(f"用户说: {user_text}")
# 2. AI处理
ai_response = self.chat(user_text)
print(f"AI回复: {ai_response}")
# 3. 文字转语音
audio_output = self.text_to_speech(ai_response)
return ai_response, audio_output
# 使用示例
assistant = MultimodalAssistant()
# 文本对话
response = assistant.chat("解释一下什么是RAG")
print(response)
# 图片分析
description = assistant.analyze_image(
"architecture.png",
"这个系统架构有什么优缺点?"
)
print(description)
# 语音交互
text_response, audio_file = assistant.voice_interaction("user_question.mp3")
print(f"文字回复: {text_response}")
print(f"语音文件: {audio_file}")
6.3 进阶:流式语音合成
import io
from openai import OpenAI
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def stream_text_to_speech(text: str) -> bytes:
"""流式语音合成,边生成边返回"""
stream = client.audio.speech.create(
model="tts-1",
voice="alloy",
input=text,
stream=True
)
audio_buffer = io.BytesIO()
for chunk in stream.iter_bytes():
audio_buffer.write(chunk)
audio_buffer.seek(0)
return audio_buffer.getvalue()
# 获取流式音频数据
audio_data = stream_text_to_speech("这是一段流式合成的语音测试。")
print(f"生成音频大小: {len(audio_data)} bytes")
七、常见问题与处理
7.1 图片上传失败
问题:图片太大导致API报错
解决:控制图片大小,建议不超过5MB
from PIL import Image
def resize_image_if_needed(image_path: str, max_size_mb: int = 5) -> str:
"""如果图片太大就压缩"""
img = Image.open(image_path)
# 检查文件大小
file_size = os.path.getsize(image_path) / (1024 * 1024)
if file_size > max_size_mb:
# 按比例缩放
scale = (max_size_mb / file_size) ** 0.5
new_size = (int(img.width * scale), int(img.height * scale))
img = img.resize(new_size, Image.LANCZOS)
output_path = image_path.replace(".png", "_compressed.png")
img.save(output_path, optimize=True)
return output_path
return image_path
7.2 Whisper转录中文不准确
问题:中文专有名词识别错误
解决:使用prompt提供上下文
def transcribe_tech_content(audio_path: str) -> str:
"""转录技术类音频,使用上下文提示"""
with open(audio_path, "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language="zh",
prompt="以下内容涉及AI技术:LangChain、Vector Database、RAG、Embedding、Claude、GPT、Token、Prompt Engineering、Function Calling、Agent"
)
return result
7.3 TTS生成语音太长被截断
问题:文本太长时可能被截断
解决:分段处理
def long_text_to_speech(text: str, max_chars: int = 4000) -> str:
"""处理长文本,分段合成"""
# 按句子拆分
sentences = text.replace("。", "。|").replace("!", "!|").replace("?", "?|").split("|")
sentences = [s.strip() for s in sentences if s.strip()]
output_files = []
for i, sentence in enumerate(sentences):
# 如果单句仍然太长,进一步拆分
if len(sentence) > max_chars:
# 按段落拆分
chunks = [sentence[i:i+max_chars] for i in range(0, len(sentence), max_chars)]
for chunk in chunks:
output_file = f"temp_chunk_{i}.mp3"
text_to_speech(chunk, output_file)
output_files.append(output_file)
else:
output_file = f"temp_chunk_{i}.mp3"
text_to_speech(sentence, output_file)
output_files.append(output_file)
# 合并音频文件(略,需要pydub)
return f"合并了{len(output_files)}个片段"
7.4 多模态API成本参考
| 功能 | 模型 | 费用(参考) |
|---|---|---|
| 图片理解 | GPT-4o | $0.021/图(1024x1024) |
| 图片理解 | Claude 3.5 | 按token计费 |
| 语音识别 | Whisper-1 | $0.006/分钟 |
| 语音合成 | TTS-1 | $0.015/1000字符 |
八、总结
| 技能 | 关键代码 | 说明 |
|---|---|---|
| 图片URL分析 | image_url: {"url": url} |
GPT-4o直接分析网络图片 |
| 图片Base64分析 | data:image/png;base64,{data} |
本地图片转base64后分析 |
| Claude图片分析 | {"type": "image", "source": {...}} |
Claude格式略有不同 |
| 语音转文字 | audio.transcriptions.create(model="whisper-1") |
支持多语言 |
| 文字转语音 | audio.speech.create(model="tts-1") |
6种音色可选 |
| 多模态助手 | MultimodalAssistant类 | 综合实战项目 |
多模态让AI更接近人类:看图、听话、说话——这些能力组合起来,已经能实现很多实用的AI应用了。
更多内容
如果你对AI开发、Agent实战感兴趣,欢迎关注我的公众号【码头码农】:
- 每日AI热点解读
- 实战项目复盘
- 技术成长心得
扫码关注,一起进步👇
本文为《AI开发实战》系列课程 · 系列一:大模型应用开发入门 · 第7篇
更多推荐
所有评论(0)