RAG多模态(一):从概念到 Gemini / DashScope 实战
在传统 RAG 里,我们最常见的输入是文本:用户提问,系统去向量库里检索相关文本片段,再交给大模型生成答案。
但真实世界里的信息并不只有文本,还有图片、截图、表格、音频、视频、PDF,甚至代码文件。
如果你的知识库、业务流程、产品资料、实验记录里包含这些内容,那么只做“文本 RAG”就不够用了。
这时候,就轮到 多模态 RAG 上场。
什么是多模态
多模态(Multimodal)并不神秘:本质上就是把图片 / 文本 /(可选:音频)放进同一个请求里,让模型基于这些输入生成结果。
更具体一点说,多模态模型可以同时理解不同类型的数据,并在同一条推理链路里完成:
- 内容识别
- 语义理解
- 关系推理
- 信息抽取
- 文本生成
这和“先把图片 OCR 成文本,再把文本喂给模型”的方案不一样。
后者是典型的串联式流程,前者则是模型原生支持多种输入,通常在理解复杂场景时更自然,也更少丢信息。
对于 RAG 来说,多模态的价值主要体现在两点:
- 检索对象不再局限于纯文本
- 生成答案时可以直接参考图片、视频帧、PDF 页面等原始信息
为什么 RAG 需要多模态
很多业务场景天然就是多模态:
- 电商:商品图、详情页、用户评论、说明书
- 教育:课件、扫描版 PDF、板书截图
- 工业:设备照片、巡检视频、故障日志
- 文档管理:合同 PDF、流程图、表格截图、演示稿
如果知识库里存的是图片或 PDF 页面,仅靠文本切片会遇到两个问题:
- 关键信息可能根本没有被完整转成文本
- 图文关系会丢失,比如“这张图对应哪一段说明”
所以,多模态 RAG 的核心不是“炫技”,而是让系统保留更多原始信息,提高检索和回答的准确性。
Gemini 的多模态处理能力
Gemini 的一个典型优势,就是它可以把不同形态的数据一次性喂给模型:
- 文本
- 图像
- 音频
- 视频
- 代码
它能在同一套神经网络里完成理解、推理、生成,无需先强制转成文本再处理。
对开发者来说,这意味着你可以直接把“文件对象”或者“多段输入”组合起来发给模型,让它根据上下文做分析。
如果你要申请 Gemini API Key,可以到这里:
https://aistudio.google.com/app/api-key
Gemini 示例:图片理解
下面这段逻辑代码来自 1-Gemini多模态处理.py 。核心点很简单:
把图片对象和问题文本放到同一个 contents 里,模型会同时看图和看字。
from google import genai
from PIL import Image
client = genai.Client()
image = Image.open("dog_and_girl.jpeg")
response = client.models.generate_content(
model="gemini-3-flash-preview",
contents=[image, "帮我解释一下这张照片里发生了什么?"],
)
print(response.text)
这段代码做了什么
genai.Client():初始化 Gemini 客户端Image.open(...):读取本地图片contents=[image, "问题"]:把图像和文本一起传给模型response.text:输出模型生成的自然语言结果
这个模式特别适合:
- 看图问答
- 截图分析
- 商品图理解
- 票据、表单、海报信息抽取
Gemini 示例:视频理解
多模态不只看图,也能看视频。
视频的典型处理流程是先上传,再等待云端完成处理,然后把视频文件对象放进请求里。
import time
from google import genai
client = genai.Client()
print("正在上传视频...")
video_file = client.files.upload(file="car.mp4")
print(f"上传成功: {video_file.name}")
while video_file.state.name == "PROCESSING":
print("视频处理中,请稍候...")
time.sleep(2)
video_file = client.files.get(name=video_file.name)
if video_file.state.name == "FAILED":
raise ValueError("视频处理失败")
response = client.models.generate_content(
model="gemini-3-flash-preview",
contents=[
video_file,
"详细描述视频里发生了什么,如果有对话,请提取关键对话。",
],
)
print(response.text)
这里的关键点
- 视频不能像普通文本一样直接塞进去,通常需要先上传
PROCESSING轮询是必要步骤,因为视频需要云端转码/索引- 处理完成后,再让模型结合视频内容做总结、抽取、问答
这种方式很适合:
- 行车记录视频分析
- 培训视频总结
- 监控画面事件抽取
- 课程录像摘要
Gemini 在多模态 RAG 里的用法
如果把 Gemini 放进 RAG 系统里,常见做法有两种:
1. 作为“理解器”
先让 Gemini 理解图片、PDF、视频内容,再把结果结构化成文本或 JSON,后续进入向量库检索。
适合:
- 需要建立索引
- 需要抽取实体、标签、摘要
- 需要统一元数据格式
2. 作为“回答器”
先检索相关图片页、PDF 页、视频片段,再把这些原始内容直接交给 Gemini,让它基于证据生成答案。
适合:
- 强依赖原图原文的问答
- 需要保留版式、图表、截图上下文
- 不能丢失视觉信息的场景
DashScope 版本:一个可替代的多模态方案
考虑到在国内 Gemini 的 apikey 申请有门槛,我也准备了一个 DashScope 的实例:dashscope多模态处理.py。
这个版本的思路很实用:
给模型一张图片,然后要求它严格输出 JSON,方便后续程序继续处理。
核心目标
- 输入:图片
- 输出:结构化 JSON
- 重点:保证可解析、可落库、可检索
代码结构
import json
import os
import re
from typing import Any
import dashscope
from dashscope import MultiModalConversation
先看最关键的三步:
- 读取并校验 API Key
- 构造多模态消息
- 解析模型输出并转成 JSON
DashScope 示例:API Key 校验
def require_dashscope_key() -> None:
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
if not dashscope.api_key:
raise ValueError("请先设置环境变量 DASHSCOPE_API_KEY")
这一段很适合放在脚本入口之前,避免用户跑到一半才发现没配密钥。
DashScope 示例:提示词设计
def build_prompt() -> str:
return (
"你是一个严谨的识图助手。请根据图片内容提取关键信息,并严格输出 JSON。"
"不要输出解释文字,不要使用 Markdown 代码块。"
'输出格式:{"summary": string, "entities": [string], "need_more_info": [string]}'
)
这段提示词的设计重点有两个:
- 明确角色:识图助手
- 明确输出格式:必须是 JSON
在生产环境里,这种写法非常重要。
因为你并不是只想“看懂图片”,而是要把结果变成可继续处理的数据。
DashScope 示例:构造多模态消息
def build_messages(image_url: str) -> list[dict[str, Any]]:
return [
{
"role": "user",
"content": [
{"text": build_prompt()},
{"image": image_url},
],
}
]
这里可以看到,文本和图片被放到了同一个 content 数组里。
这就是典型的多模态请求结构。
DashScope 示例:解析返回内容
def parse_json_response(text: str) -> dict[str, Any]:
cleaned = text.strip()
if cleaned.startswith("```"):
cleaned = re.sub(r"^```(?:json)?\s*", "", cleaned, flags=re.IGNORECASE)
cleaned = re.sub(r"\s*```$", "", cleaned)
try:
return json.loads(cleaned)
except json.JSONDecodeError:
match = re.search(r"\{.*\}", cleaned, flags=re.S)
if match:
return json.loads(match.group(0))
raise RuntimeError(f"模型未返回合法 JSON:{text}")
这段代码非常实用,因为模型有时会:
- 直接输出 JSON
- 把 JSON 包在 Markdown 代码块里
- 多输出几句解释文字
所以在工程里,不能假设模型输出“永远完美”。
更稳妥的做法是做一次清洗,再尽可能从返回文本中恢复 JSON。
DashScope 示例:完整调用入口
def parse_image_to_json(image_url: str) -> dict[str, Any]:
require_dashscope_key()
resp = MultiModalConversation.call(
model="qwen-vl-plus",
messages=build_messages(image_url),
)
text = resp.output.choices[0].message["content"][0]["text"]
return parse_json_response(text)
这里的流程很清晰:
- 先确认密钥
- 再发起多模态调用
- 最后把结果转成 JSON
如果你要把它接入 RAG,可以在这个 JSON 基础上继续做:
- 标签入库
- 文本摘要入库
- 结构化字段索引
- 后续语义检索
Gemini 和 DashScope 怎么选
如果你的目标是:
- 测试前沿多模态能力
- 处理视频、PDF、复杂输入
- 需要比较强的通用推理能力
可以优先看 Gemini。
如果你的目标是:
- 国内环境更稳定地接入
- 需要中文场景支持
- 想快速把图片识别结果结构化
DashScope 是很好的替代方案。
从工程实践看,最好的方式不是“二选一”,而是把多模态能力做成可替换适配层:
- 上层统一输入输出协议
- 底层按环境切换 Gemini / DashScope / 其他模型
这样你的 RAG 主流程不会被单一厂商锁死。
多模态 RAG 的落地建议
如果你正在做一个真正可用的多模态 RAG,我建议优先关注这几件事:
- 先定义数据结构
- 再定义每种模态的抽取策略
- 抽取结果尽量结构化
- 保留原始文件与处理结果的映射关系
- 对模型输出做容错和校验
一个比较稳的流程通常是:
原始文件 -> 多模态理解 -> 结构化抽取 -> 索引构建 -> 检索 -> 生成答案
对于图片、PDF、视频这类内容,建议至少保留:
- 原始文件路径或 URL
- 文件类型
- 页码 / 帧号 / 时间戳
- 摘要
- 关键词
- 结构化实体
这样在回答阶段,你才能把“证据”精确地找回来。
小结
多模态并不是一个复杂的概念,本质上就是让模型同时处理图片、文本、音频、视频等不同输入。
在 RAG 场景里,多模态的价值非常直接:
- 信息保留更完整
- 检索对象更丰富
- 回答依据更可靠
本文给了两个可参考的方向:
Gemini:更偏原生多模态理解,适合图片、视频、PDF 等输入DashScope:更适合做结构化识图和国内环境落地
如果你后续要把这一套继续扩展成完整的多模态 RAG,我建议下一步重点做:
- 图片 / PDF / 视频的统一切片策略
- 结构化元数据设计
- 多模态向量索引构建
- 检索结果与原始素材的对齐
资源说明
- Gemini 示例代码:
CASE-Gemini多模态处理/1-Gemini多模态处理.py - DashScope 示例代码:
CASE-Gemini多模态处理/dashscope多模态处理.py - Gemini API Key 申请地址:
https://aistudio.google.com/app/api-key
更多推荐



所有评论(0)