模态路由、时间对齐与压缩
正在读取学习记录…
多模态 Agent 接收文字、图片和声音。模态是信息的表现形式:订单截图提供表格位置,声音提供“查这张订单”的请求。模态路由负责选择哪些输入交给哪个处理器;时间对齐负责把同一时刻的信息配对;压缩负责留下足以完成任务的材料。
观看录屏时,人在 1080 毫秒说“查这张订单”,画面在 1000 毫秒切到订单表。两者相差 80 毫秒,允许误差 120 毫秒时可配成一组。像会议纪要需要把“这一页”对应到当时展示的幻灯片:若把话配到一分钟前的封面,句子虽然没有错,指代却错了。
从输入到可核对结果
输入是人工给定的三条画面描述与一条语句时间戳。它们代表采集器与识别器已经产出的记录,程序实际执行最近时间匹配与记录压缩。
先用绝对时间差找到最近的一帧,再用 tolerance 检查是否接近。通过后保留原时间戳、画面描述、文字和gap_ms,这些字段帮助后续模型知道图文如何关联。真实视频的采样间隔、语音识别返回延迟和设备时钟差都会影响对齐:录制时刻与识别完成时刻要分开。OpenAI 图像输入文档说明模型图像输入的组织方式;处理器接收哪个模态是应用侧路由决策。
route 把任务名称映射到处理器和所需载荷,缺少任一必要模态就拒绝。音频、图像用人工材料标签表示,函数实际构造路由载荷;ASR与视觉模型在应用接入后消费这些载荷。
| 任务 | 处理器 | 需要的载荷 | 缺材料时 |
|---|---|---|---|
| 转写录音 | ASR | audio音频片段 | 停止提交 |
| 读图金额 | 视觉 | image订单截图 | 等待图片 |
| 解释这张图 | 图文 | image与text指代语句 | 补齐两种材料 |
压缩动作随任务选择。采样减少帧数,可能漏掉两帧之间的事件;裁剪保留目标区域,可能丢失位置与周边关系;摘要保留关键句,可能损失原词、语调或精确数字。需要逐字转写时保留音频,需要核对金额时保留原图文字区域,需要判断事件先后时保留时间戳。本例采用最近帧采样,并留下帧时间与语句作为对应依据。
| 画面时间 | 画面内容 | 到1080ms的距离 | 选择结果 |
|---|---|---|---|
| 0ms | 封面 | 1080ms | 舍弃 |
| 1000ms | 订单表 | 80ms | 保留 |
| 2000ms | 物流图 | 920ms | 舍弃 |
保存并运行这两个文件
在 PowerShell 创建练习目录:
New-Item -ItemType Directory -Force l9-multimodal
cd l9-multimodalmacOS 终端:
mkdir -p l9-multimodal
cd l9-multimodal把下面第一段完整代码保存为 align_lab.py,第二段保存为 test_align_lab.py,两份文件放在这个目录。
TOLERANCE_MS = 120
FRAMES = [(0, "封面"), (1000, "订单表"), (2000, "物流图")]
UTTERANCE = (1080, "查这张订单")
def align(frames, utterance, tolerance):
if tolerance < 0:
raise ValueError("时间容差不能为负数")
if not frames:
return None
# 时间戳单位统一为毫秒;用绝对距离选择最近画面。
stamp, text = utterance
nearest = min(frames, key=lambda frame: abs(frame[0] - stamp))
distance = abs(nearest[0] - stamp)
if distance > tolerance:
return None
# 压缩保留任务相关的一帧、原时间戳和语句,便于追溯。
return {"route": "图文", "frame_ms": nearest[0],
"frame": nearest[1], "text": text, "gap_ms": distance}
def route(task, *, image=None, audio=None, text=None):
# 路由是应用规则:材料送往哪个处理器,并把缺少的模态及时返回。
choices = {
"转写录音": ("ASR", {"audio": audio}),
"读图金额": ("视觉", {"image": image}),
"解释这张图": ("图文", {"image": image, "text": text}),
}
if task not in choices:
raise ValueError("未知任务")
processor, payload = choices[task]
if any(value is None or value == "" for value in payload.values()):
raise ValueError("任务所需模态缺失")
return {"processor": processor, "payload": payload}
if __name__ == "__main__":
result = align(FRAMES, UTTERANCE, TOLERANCE_MS)
if result is None:
print("路由:等待更接近的画面")
else:
bundle = route("解释这张图", image=result["frame"], text=result["text"])
print("路由:" + bundle["processor"])
print("保留画面:" + result["frame"] + ",时间=" + str(result["frame_ms"]) + "ms")
print("对齐误差:" + str(result["gap_ms"]) + "ms")
print("压缩:3帧 → 1帧")
audio_route = route("转写录音", audio="录音片段A")
image_route = route("读图金额", image="订单截图A")
print("录音任务 → " + audio_route["processor"] + ",载荷键=audio")
print("读图任务 → " + image_route["processor"] + ",载荷键=image")import unittest
import align_lab as lab
class MechanismTests(unittest.TestCase):
# 正常、边界和失败输入都由这里提供,直接运行即可。
def test_normal(self):
self.assertEqual(lab.align(lab.FRAMES, lab.UTTERANCE, 120)["frame"], "订单表")
self.assertEqual(lab.route("转写录音", audio="片段")["processor"], "ASR")
self.assertEqual(lab.route("读图金额", image="图")["payload"], {"image": "图"})
self.assertEqual(lab.route("解释这张图", image="图", text="解释")["processor"], "图文")
def test_boundary_tolerance(self):
self.assertEqual(lab.align(lab.FRAMES, lab.UTTERANCE, 80)["gap_ms"], 80)
self.assertIsNone(lab.align([], lab.UTTERANCE, 80))
def test_failure(self):
self.assertIsNone(lab.align(lab.FRAMES, lab.UTTERANCE, 79))
with self.assertRaises(ValueError):
lab.align(lab.FRAMES, lab.UTTERANCE, -1)
with self.assertRaises(ValueError):
lab.route("解释这张图", image="图")
with self.assertRaises(ValueError):
lab.route("未知任务", text="请求")
if __name__ == "__main__":
unittest.main()打开 PowerShell,逐行输入下列命令。cd 是进入文件夹,dir 是列出文件;确认列表里有刚保存的两个 .py 文件,再运行 Python。
# 在刚才创建的练习目录检查文件,再运行程序。
ls
python -X utf8 align_lab.py
python -X utf8 -m unittest -v test_align_lab.py程序输出:
路由:图文
保留画面:订单表,时间=1000ms
对齐误差:80ms
压缩:3帧 → 1帧
录音任务 → ASR,载荷键=audio
读图任务 → 视觉,载荷键=image测试末尾应显示 Ran 3 tests 与 OK。若找不到文件,检查当前目录与扩展名;若导入失败,确认测试和主程序在同一文件夹。测试描述的三组材料就在上方代码,不需要另外准备输入。
改一处,再看结果
输出显示路由为“图文”,保留订单表而不是封面或物流图。压缩从三帧降到一帧,缩减的是本次请求材料,原始采集资料仍应按保存策略处理。压缩不能只看字节数:一句“这张图”如果失去对应画面,材料就失去了任务意义。
把 TOLERANCE_MS = 120 改成 TOLERANCE_MS = 79,保存并重跑。80 毫秒超出门限,图文任务输出“等待更接近的画面”;不需要这次画面的转写与读图任务仍各自显示处理器。恢复为 120 后重新运行。测试还给出正好等于80的边界,此时应通过。
模态选择要跟着任务:抄图片里的金额应保留文字分辨率,理解表格关系应保留行列结构,分析声调则需要音频而非仅转写文字。接入真实图像或语音服务时,检查个人资料是否需要上传,再按服务实际计费方式限制采样与请求数量。
改动后仍在刚才的 PowerShell 目录运行:
python -X utf8 align_lab.py确认上述变化后,把参数恢复成原值,保存并再次执行这条命令。
把机制接回 Agent
采集层应为视频帧和音频段标注同一时钟下的时间戳,语音转写再带回对应音频段时间。路由层根据任务选择图像、音频或图文组合,对齐层输出有出处的材料包。下游模型回答时保留引用帧与时间,用户才能回到原记录核对指代。
课后练习展开习题收起习题
正在读取本地记录…
不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。
选择题 · 先判断边界
关于“模态路由、时间对齐与压缩”,哪种做法更稳妥?
对应知识点:L9-multimodal
简答题 · 解释失败
写出一个失败输入并说明记录字段。
对应知识点:L9-multimodal
代码题 · 边界测试
补充正常、边界、失败三组输入和预期结果。
对应知识点:L9-multimodal
场景题 · 结果未知
证据不足时如何设计状态和人工接管?
对应知识点:L9-multimodal
描述会发送给本站维护者,用于修订文章,保存90天。请只填写文章问题,省略个人信息、密钥和内部资料。