paper2skills Playbook

LMM-Searcher — 长链多模态 Agent:UID 占位符按需加载图片

Skill-LMM-Searcher-Multimodal-Context · 16-智能体工程

causalexperimentmulti_agentvisual_generation推荐与搜索MAS与智能体工程风控与合规视觉内容生成WF-D 选品扫描WF-G Listing内容优化
实现难度⭐⭐☆☆☆
业务优先级⭐⭐⭐⭐☆
业务视角
适用角色CTO / 技术负责人 · 产品经理 · 数据工程师
适用平台跨境运营 AI Agent 工程落地 · Amazon SP API + LLM 集成 · 多平台数据采集 Agent
什么情况下用想把 AI 集成到业务系统,但 LLM 稳定性差、幻觉问题、成本控制都是挑战;Agent 任务失败了不知道哪步出了问题
成功是什么样的AI Agent 在生产环境稳定运行,失败可追踪,成本可控,复杂任务完成率 >85%
业务痛点
LLM 返回结果不稳定不可靠AI 幻觉导致业务决策错误Agent 任务失败了不知道哪步出问题AI 调用成本控制不住

1. 解决的问题

LMM-Searcher 解决长链多模态 Agent 的上下文爆炸问题:在 100 轮搜索会话中,若每张图片直接嵌入为 base64(约 1,000-3,000 tokens),50 张图片就会占用 50,000-150,000 tokens,远超实用预算。

2. 核心算法逻辑

LMMSearcher 解决长链多模态 Agent 的上下文爆炸问题:在 100 轮搜索会话中,若每张图片直接嵌入为 base64(约 1,0003,000 tokens),50 张图片就会占用 50,000150,000 tokens,远超实用预算。

3. 业务应用场景

业务问题:选品 Agent 一次搜索 10 个竞品,每个竞品有 6-8 张产品图(主图、详情图、包装图),Agent 需跨图对比外观、认证标志、卖点差异。

传统做法:全部图片嵌入 context,10 竞品 × 7 图 × 2,000 tokens = 14 万 tokens,每次查询成本约 ¥2.1。

UID 占位模式: - 注册阶段:70 张图存入 ImageRegistry,context 仅含 UID 占位串(70 × 30 = 2,100 tokens) - Agent 决策:仅在需要"细节对比"时 fetch(通常 5-8 张),按需加载 5 × 2,000 = 10,000 tokens - token 减少约 70%,成本降至 ¥0.63/次 - 每月节省(100 次/天 × 30 天):约 ¥180-300

4. 输入数据要求

请查看原始代码模板获取输入规格。

5. 输出结果

请查看原始代码模板获取输出规格。

6. 业务价值 / ROI

未自动抽取;请查看原始 Skill 卡片。

7. 代码模板

代码块数量:1 · 路径:未检测到

"""
LMM-Searcher: UID 占位符 + 按需加载图片的长链多模态 Agent 上下文管理
参考: arXiv:2604.12890 — LMM-Searcher: Long-horizon Agentic Multimodal Search
"""
from __future__ import annotations

import base64
import hashlib
import io
import json
import os
import time
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional

# ─────────────────────────────────────────────
# 1. ImageRegistry:图片外部存储与 UID 管理
# ─────────────────────────────────────────────

class ImageRegistry:
    """
    外部图片注册中心。图片以 base64 存储在内存 dict 中(生产环境可替换为文件系统/对象存储)。
    register_image() → uid;fetch_image(uid) → base64 字符串
    """

    def __init__(self):
        self._store: dict[str, str] = {}         # uid → base64
        self._meta: dict[str, dict] = {}          # uid → metadata
        self._counter: int = 0

    def register_image(
        self,
        source: str | bytes,
        description: str = "",
        metadata: Optional[dict] = None,
    ) -> str:
        """
        注册图片,返回 UID。
        source: 本地文件路径、URL字符串,或原始 bytes
        """
        uid = f"IMG_UID_{self._counter:04d}"
        self._counter += 1

        if isinstance(source, bytes):
            b64 = base64.b64encode(source).decode()
        elif isinstance(source, str) and os.path.isfile(source):
            with open(source, "rb") as f:
                b64 = base64.b64encode(f.read()).decode()
        elif isinstance(source, str) and source.startswith("http"):
            # 生产环境替换为真实 HTTP 下载;此处用 mock 数据
            mock_bytes = f"[MOCK_IMAGE_DATA:{source}]".encode()
            b64 = base64.b64encode(mock_bytes).decode()
        else:
            b64 = base64.b64encode(str(source).encode()).decode()

        self._store[uid] = b64
        self._meta[uid] = {
            "description": description,
            "source": str(source)[:100],

8. 论文来源

  • 2604.12890