Python实战:Gemini API多模态与流式处理深度解析
1. 从零开始:你的第一个Gemini API调用
如果你刚接触Gemini API,可能会觉得有点复杂,但别担心,我刚开始用的时候也这样。其实只要几步,你就能让这个强大的AI模型为你工作。我建议你先从最简单的文本生成开始,感受一下它的能力。
首先,你得有个API密钥。这个密钥就像是你进入Gemini世界的门票。你可以去Google AI Studio免费申请一个。拿到密钥后,我习惯把它设置成环境变量,这样代码里就不用硬编码,更安全。在终端里输入 export GEMINI_API_KEY='你的密钥'(Windows用 set GEMINI_API_KEY='你的密钥')就行。
接下来安装Python库。官方推荐用 google-generativeai 这个库,它封装得比较好,用起来顺手。直接 pip install google-generativeai 就能搞定。我实测下来,Python版本最好在3.9以上,不然可能会遇到一些兼容性问题。
安装好了,我们来写第一个程序。这个程序简单到只有几行,但能让你立刻看到效果:
import google.generativeai as genai
import os
# 配置API密钥,这里会从环境变量GEMINI_API_KEY读取
genai.configure(api_key=os.getenv('GEMINI_API_KEY'))
# 创建一个模型实例,这里用gemini-pro,这是最通用的文本模型
model = genai.GenerativeModel('gemini-pro')
# 发送一个简单的请求
response = model.generate_content("用一句话解释什么是机器学习?")
print(response.text)
运行这段代码,你应该能看到一句关于机器学习的简洁解释。我第一次跑的时候,感觉特别神奇,几行代码就能调用世界顶级的AI模型。这里有个小细节要注意,generate_content 方法返回的对象里,真正的文本在 response.text 属性里。如果你直接打印 response,会看到一堆元数据,反而找不到答案。
你可能想知道还有哪些模型可用。其实Gemini提供了好几个模型,针对不同场景优化。我常用 genai.list_models() 来查看所有可用模型:
for model in genai.list_models():
if 'generateContent' in model.supported_generation_methods:
print(f"模型: {model.name}")
print(f"描述: {model.description}")
print("-" * 30)
这会列出所有支持内容生成的模型,比如 gemini-pro 适合通用文本任务,gemini-pro-vision 能处理图片,还有各种尺寸的模型适应不同算力需求。刚开始我建议先用 gemini-pro,它平衡了能力和速度,免费额度也够用。
2. 流式输出:让AI的回答像真人一样“打字”
不知道你有没有用过那些一个字一个字往外蹦的AI聊天应用?那种体验特别自然,就像对面真有人在思考打字一样。这就是流式输出的魅力。我第一次实现这个功能时,感觉整个应用的交互体验提升了一个档次。
传统的API调用是“阻塞式”的——你发送请求,然后干等着,直到整个回答生成完毕才一次性返回。对于长回答,用户可能要等好几秒,看着空白的界面,心里会想“是不是卡住了?”。流式输出就解决了这个问题,模型生成一点,就返回一点,用户能立即看到反馈。
用Gemini API实现流式输出简单得惊人,只需要加一个参数:
def stream_response(prompt):
genai.configure(api_key=os.getenv('GEMINI_API_KEY'))
model = genai.GenerativeModel('gemini-pro')
# 关键就在这里:stream=True
response = model.generate_content(prompt, stream=True)
# 然后像遍历普通列表一样遍历response
for chunk in response:
print(chunk.text, end='', flush=True)
# 这里可以加上延迟,模拟真人打字速度
# time.sleep(0.05)
print() # 最后换行
if __name__ == '__main__':
stream_response("给我讲一个关于程序员的笑话")
运行这段代码,你会看到笑话是一个词一个词出现的,而不是一下子全出来。我在实际项目中发现,这种体验对用户特别友好,尤其是生成长文本时,用户不会因为等待而焦虑。
但流式输出不只是为了好看,它还有实际的技术优势。想象一下你要生成一篇5000字的文章,如果一次性生成,内存里要保存整个响应,而流式处理可以边生成边处理,内存占用小得多。我做过一个项目,需要实时处理AI生成的代码并立即语法高亮,流式输出让这变得可能。
不过流式输出也有些坑需要注意。最大的问题是“断句”——模型返回的chunk不一定在完整的句子或单词边界处切断。你可能收到半个词,或者标点符号和前文分开了。我的经验是,在前端展示时要做一些缓冲处理,比如积累几个chunk再一起渲染,或者智能地判断断句位置。
另一个实际问题是错误处理。在非流式调用中,如果有错误,整个请求会失败,你收到一个异常。但在流式调用中,错误可能发生在中间某个chunk。我建议这样处理:
try:
response = model.generate_content(prompt, stream=True)
for chunk in response:
if chunk.parts and chunk.parts[0].text:
print(chunk.text, end='', flush=True)
elif chunk.prompt_feedback:
# 处理安全过滤或其他反馈
print(f"\n注意: {chunk.prompt_feedback}")
except Exception as e:
print(f"流式请求出错: {e}")
我还发现一个有趣的现象:不同内容的流式输出速度不一样。简单的事实性问题,chunk来得又快又大段;复杂的推理问题,chunk来得慢但更“深思熟虑”。你可以利用这个特性给用户提示——如果chunk间隔长,显示“正在思考...”的动画。
3. 多模态实战:让AI“看懂”图片
Gemini真正厉害的地方在于多模态能力——它不仅能处理文字,还能理解图片。我第一次让AI描述我上传的猫咪照片时,那种感觉就像魔法。它不仅能认出是猫,还能说出品种、姿势、甚至情绪。
要用这个功能,你需要 gemini-pro-vision 模型。安装依赖很简单:pip install pillow。Pillow是Python里处理图片的标准库。
来看一个完整的例子:
import google.generativeai as genai
import PIL.Image
import os
def analyze_image(image_path, prompt="描述这张图片"):
genai.configure(api_key=os.getenv('GEMINI_API_KEY'))
model = genai.GenerativeModel('gemini-pro-vision')
# 加载图片
img = PIL.Image.open(image_path)
# 同时发送文本提示和图片
response = model.generate_content([prompt, img])
print(response.text)
if __name__ == '__main__':
# 你可以换成自己的图片路径
analyze_image("cat.jpg", "这只猫在做什么?它的情绪看起来怎么样?")
我测试过各种图片,从简单的图表到复杂的风景照,Gemini的表现都令人印象深刻。有一次我上传了一张满是文字的截图,问它“这里面讲了什么”,它居然准确地总结了内容,还提取了关键信息。
但多模态功能不只是“看图说话”那么简单。在实际项目中,我常用它来做这些事:
信息提取:上传一张收据,让AI提取金额、商家、日期。以前要用OCR加规则引擎,现在几行代码搞定:
receipt_img = PIL.Image.open("receipt.jpg")
response = model.generate_content([
"提取这张收据上的以下信息,以JSON格式返回:",
"1. 商家名称 2. 总金额 3. 日期 4. 商品列表",
receipt_img
])
内容审核:自动检查用户上传的图片是否合适。这比传统的图像识别模型灵活多了,因为你可以用自然语言描述审核规则:
response = model.generate_content([
"这张图片是否包含不适合公开的内容?",
"只回答'是'或'否',然后简要说明原因。",
user_image
])
创意辅助:我有个做设计的朋友,经常上传草图让AI给建议:
response = model.generate_content([
"这是一张网站首页的草图,",
"请从UI/UX角度给出3条改进建议,",
"并指出色彩搭配是否协调。",
design_sketch
])
多模态调用有个成本问题需要留意。图片会占用大量token,特别是高分辨率图片。Gemini API会根据图片尺寸和复杂度计算token消耗。我的经验是,如果不需要分析细节,可以先压缩图片。但要注意,压缩太厉害可能丢失关键信息。
还有一个实用技巧:你可以同时上传多张图片让AI分析关系。比如上传产品的前后左右视图,问它“这些是同一个产品的不同角度吗?”或者上传“之前”和“之后”的对比图,让AI描述变化。
4. 代码执行:让AI不仅说,还能做
这是Gemini最新也是最强大的功能之一——代码执行。简单说,就是AI不仅能回答问题,还能写代码并执行它,然后把结果告诉你。我第一次用这个功能时,感觉就像有个程序员同事在旁边,你说需求,他现场写代码跑给你看。
想象一下这个场景:你上传一张数据图表图片,问“这组数据的平均值是多少?”传统AI只能猜,但有了代码执行能力,AI可以写Python代码读取图片中的数据点,计算平均值,然后告诉你准确结果。
要启用代码执行,需要在请求配置中指定工具。最新版的Gemini 3 Flash模型对这个功能支持最好:
from google import genai
from google.genai import types
import requests
from PIL import Image
import io
def analyze_with_code_execution(image_url, question):
client = genai.Client()
# 下载图片
image_bytes = requests.get(image_url).content
response = client.models.generate_content(
model="gemini-3-flash-preview",
contents=[
types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"),
question
],
config=types.GenerateContentConfig(
tools=[types.Tool(code_execution=types.ToolCodeExecution())]
),
)
# 处理响应,可能包含文本、代码和执行结果
for part in response.candidates[0].content.parts:
if part.text is not None:
print("AI说:", part.text)
if part.executable_code is not None:
print(f"\n生成的代码 ({part.executable_code.language}):")
print(part.executable_code.code)
if part.code_execution_result is not None:
print("\n代码执行结果:")
print(part.code_execution_result.output)
# 示例:分析图片中的仪表盘
analyze_with_code_execution(
"https://example.com/gauge.jpg",
"放大看这个仪表盘的读数区域,告诉我指针指向多少?"
)
这个功能特别适合需要精确计算或数据提取的场景。我举几个实际用过的例子:
数学计算:以前让AI算数学题,它可能瞎猜。现在它可以正经写代码算了:
response = client.models.generate_content(
model="gemini-3-flash-preview",
contents="计算前100个质数的和,写出代码并执行验证",
config=types.GenerateContentConfig(
tools=[types.Tool(code_execution=types.ToolCodeExecution())]
),
)
图像处理:让AI分析图片并标注:
response = client.models.generate_content(
model="gemini-3-flash-preview",
contents=[
types.Part.from_bytes(data=family_photo, mime_type="image/jpeg"),
"用箭头标出图片中所有人的脸,并统计人数"
],
config=types.GenerateContentConfig(
tools=[types.Tool(code_execution=types.ToolCodeExecution())]
),
)
数据转换:上传混乱的数据表格图片,让AI整理成结构化数据。AI可以写代码识别表格、解析数据、转换成CSV。
但代码执行功能也有安全考虑。Gemini在沙箱环境中运行生成的代码,有严格限制,不能访问网络、文件系统或进行危险操作。不过在实际应用中,我还是建议:
- 仔细审查AI生成的代码再执行(虽然API自动执行,但你可以先看看)
- 不要用这个功能处理敏感数据
- 对执行时间设限,避免无限循环
我发现在聊天场景中结合代码执行特别有用。你可以先和AI讨论问题,然后让它“写段代码验证一下”。比如讨论算法时,AI可以直接给出实现并运行测试。
5. 聊天模式与上下文管理
单次问答虽然有用,但真正的对话需要记忆上下文。Gemini的聊天模式让这变得简单。我第一次实现多轮对话时,发现用户体验完全不一样——AI能记住之前说过的话,对话变得连贯自然。
最基本的聊天会话这样创建:
import google.generativeai as genai
import os
def simple_chat():
genai.configure(api_key=os.getenv('GEMINI_API_KEY'))
model = genai.GenerativeModel('gemini-pro')
# 开始一个新聊天
chat = model.start_chat(history=[])
# 发送消息
response = chat.send_message("你好,我是小明")
print(f"AI: {response.text}")
# 继续对话,AI会记住上下文
response = chat.send_message("我刚才说我叫什么名字?")
print(f"AI: {response.text}") # 它会记得你是小明
if __name__ == '__main__':
simple_chat()
但实际项目中的聊天要复杂得多。我做过一个客服机器人,需要处理这些情况:
历史记录管理:聊天会话默认会保存历史,但有时候你需要手动管理。比如用户开始新话题时,你可能想清空历史,或者只保留最近几轮对话。我发现保留10-15轮对话效果最好,再多可能让AI混乱。
系统指令:你可以给AI一个固定的身份或行为准则。这在 start_chat 时通过 system_instruction 参数设置:
chat = model.start_chat(
history=[],
system_instruction="你是一个专业的编程助手,回答要简洁准确。如果用户问与编程无关的问题,礼貌地拒绝。"
)
流式聊天:聊天也可以流式输出,体验更好:
chat = model.start_chat(history=[])
response = chat.send_message("讲一个长篇故事", stream=True)
for chunk in response:
print(chunk.text, end='', flush=True)
我在实际项目中踩过几个坑,分享给你避免:
上下文长度限制:每个模型都有token限制,gemini-pro 约32768个token。如果对话太长,最旧的消息会被丢弃。你需要监控对话长度,或者在达到限制时主动总结历史、重新开始。
历史消息格式:手动设置历史消息时,格式必须正确。必须是 user 和 model 交替的列表:
history = [
{'role':'user', 'parts': ["你好"]},
{'role':'model', 'parts': ["你好!有什么可以帮助你的?"]},
{'role':'user', 'parts': ["我想学Python"]},
{'role':'model', 'parts': ["Python是个很好的选择..."]}
]
我见过有人把role写错,或者parts不是列表,导致AI无法理解上下文。
多模态聊天:聊天中也可以混合图片和文字:
chat = model.start_chat(history=[])
img = PIL.Image.open("product.jpg")
# 第一次发送图片
response = chat.send_message([
"看看这个产品",
img
])
# 后续可以基于图片提问
response = chat.send_message("这个产品是什么颜色的?")
处理中断和恢复:在实际应用中,用户可能中途离开,稍后回来继续对话。你需要能保存和恢复聊天状态。我的做法是把历史消息序列化存储(比如用JSON),恢复时重新创建聊天:
import json
# 保存聊天
def save_chat(chat, filename):
history = chat.history
with open(filename, 'w') as f:
json.dump([{'role': msg.role, 'parts': msg.parts} for msg in history], f)
# 恢复聊天
def load_chat(model, filename):
with open(filename, 'r') as f:
history_data = json.load(f)
# 需要把parts从文本转回Part对象
history = []
for msg in history_data:
history.append({
'role': msg['role'],
'parts': msg['parts']
})
return model.start_chat(history=history)
聊天模式中最有用的功能之一是 函数调用(Function Calling)。虽然原始文章没提,但这是构建智能应用的关键。你可以定义一些函数,AI在对话中判断需要时,会请求调用这些函数。比如定义“查询天气”函数,用户问“明天天气如何”时,AI会返回函数调用请求,你执行函数后把结果给AI,AI再组织成自然语言回答。
6. 高级配置与性能调优
当你熟悉了基础用法后,肯定会想优化性能和控制成本。Gemini API提供了丰富的配置选项,我花了不少时间测试各种组合,这里分享一些实用经验。
生成配置:这是最常用的配置,控制AI如何生成内容:
from google.generativeai.types import GenerationConfig
response = model.generate_content(
"写一首关于春天的诗",
generation_config=GenerationConfig(
temperature=0.7, # 创造性,0-1,越高越随机
top_p=0.9, # 核采样,控制多样性
top_k=40, # 候选词数量
max_output_tokens=500, # 最大输出长度
stop_sequences=["###"], # 停止序列
candidate_count=1, # 生成几个候选回答
)
)
我重点说几个关键参数:
temperature:我最常调整的。写创意内容时设0.8-0.9,需要确定性答案时设0.1-0.3。默认0.7适合大多数场景。max_output_tokens:一定要设置!我有次忘了设,AI给我生成了上万字的废话,浪费token。根据场景合理设置,短回答100-200,长文章1000-2000。stop_sequences:很有用。比如让AI生成JSON时,可以设["}"]确保完整结束。
安全设置:控制AI回答的“安全等级”:
from google.generativeai.types import SafetySetting
import google.generativeai as genai
safety_settings = [
{
"category": "HARM_CATEGORY_HARASSMENT",
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"threshold": "BLOCK_ONLY_HIGH"
},
# 还有其他类别:SEXUALLY_EXPLICIT, DANGEROUS_CONTENT等
]
response = model.generate_content(
prompt,
safety_settings=safety_settings
)
安全等级从低到高有:BLOCK_NONE, BLOCK_ONLY_HIGH, BLOCK_MEDIUM_AND_ABOVE, BLOCK_LOW_AND_ABOVE。我一般用 BLOCK_MEDIUM_AND_ABOVE,在安全和实用性间取得平衡。如果AI因安全原因拒绝回答,可以通过 response.prompt_feedback 查看原因。
Token使用统计:控制成本很重要,特别是大规模使用时:
response = model.generate_content(prompt)
# 查看用了多少token
if hasattr(response, 'usage_metadata'):
print(f"输入token: {response.usage_metadata.prompt_token_count}")
print(f"输出token: {response.usage_metadata.candidates_token_count}")
print(f"总token: {response.usage_metadata.total_token_count}")
我建议记录每次调用的token使用,特别是处理图片时。一张1024x1024的图片可能消耗上千token。对于文本,英文大约1token=0.75单词,中文更复杂,1个汉字可能对应1-2个token。
超时和重试:生产环境必须有错误处理:
import time
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def generate_with_retry(prompt, max_retries=3):
for attempt in range(max_retries):
try:
response = model.generate_content(prompt, timeout=30) # 30秒超时
return response
except Exception as e:
if attempt == max_retries - 1:
raise
wait_time = 2 ** attempt # 指数退避
time.sleep(wait_time)
print(f"请求失败,{wait_time}秒后重试...")
批量处理:如果需要处理大量请求,不要一个个发,用批量:
# 假设有多个prompt
prompts = ["总结1", "总结2", "总结3"]
responses = []
for prompt in prompts:
response = model.generate_content(prompt)
responses.append(response.text)
# 或者用线程池加速
from concurrent.futures import ThreadPoolExecutor
def process_one(prompt):
return model.generate_content(prompt).text
with ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(process_one, prompts))
但要注意API的速率限制。免费版每分钟约60次请求,付费版更高。如果超限,请求会失败,需要实现限流。
缓存策略:相同的问题没必要每次都问AI。我常用简单的缓存:
import hashlib
import pickle
cache = {}
def get_cached_response(prompt, model_name="gemini-pro"):
# 用prompt和模型名生成缓存键
key = hashlib.md5(f"{prompt}_{model_name}".encode()).hexdigest()
if key in cache:
return cache[key]
response = model.generate_content(prompt)
cache[key] = response.text
return response.text
对于生产环境,可以用Redis或数据库做分布式缓存。
模型选择策略:不同任务用不同模型。我的经验是:
- 简单问答:
gemini-2.0-flash-lite(快且便宜) - 复杂推理:
gemini-2.5-pro(能力强但慢) - 多模态:
gemini-2.0-pro-vision或最新的gemini-3-flash-preview - 代码相关:
gemini-3-flash-preview(代码执行功能好)
最后提醒一点:定期检查API使用情况和费用。Google AI Studio有使用统计,设置预算提醒,避免意外费用。
更多推荐


所有评论(0)