多模态 Agent + Artifacts(E2B 沙盒)

教程:构建多模态 Agent,用 Seedream 生成图片、写分析代码、在 E2B 沙盒中执行、产出报告 Artifact。展示 SandBase 生态组合:多模态模型 + 沙盒 + LLM 一体化工作流。

结论先行 — 构建一个 Agent:接收创意 brief、用 Seedream 5 Pro 生成图片、写 Python 分析代码、在 E2B 沙盒中安全执行、产出完整报告 Artifact。本教程展示 SandBase 生态组合的工作方式:多模态生成 + 代码沙盒 + LLM 推理在单个 Agent 工作流中协同。含完整代码。

我们在构建什么

一个多模态 Agent:

  1. 接收创意 brief(如”为智能手机发布会生成主视觉”)
  2. 通过 SandBase 用 Seedream 5 Pro 生成图片
  3. 写分析代码评估图片(色彩分布、构图指标)
  4. 在 E2B 沙盒中安全执行代码
  5. 产出结构化报告 Artifact,组合图片、分析和建议

这展示了”生态组合”模式:一个 Agent 通过统一平台编排多种能力类型(生成、推理、执行)。

架构概览

创意 Brief

┌─────────────────────────────────────────────┐
│  Agent(Claude Sonnet 5 / GPT-4.1)         │
│                                             │
│  1. 解析 brief → 生成提示词                  │
│  2. 调 Seedream 5 Pro → 图片 URL            │
│  3. 写分析代码                               │
│  4. 在 E2B 沙盒执行 → 结果                   │
│  5. 综合报告 Artifact                        │
└─────────────────────────────────────────────┘
     ↓              ↓              ↓
  Seedream       E2B 沙盒       最终报告
  (图片生成)    (代码执行)     (Artifact)

三种能力(图片生成、代码执行、LLM 推理)全部通过 SandBase 统一 API 层访问。

前置要求

pip install openai e2b-code-interpreter httpx Pillow

需要的凭证:

  • SandBase API key(用于 Seedream 5 Pro + LLM)
  • E2B API key(用于沙盒执行)

完整 Agent 代码

"""
多模态 Agent + Artifacts — E2B 沙盒
生成图片、用代码分析、产出报告。
"""

import json
from pathlib import Path
from datetime import datetime
from openai import OpenAI
from e2b_code_interpreter import Sandbox

# --- 配置 ---
SANDBASE_API_KEY = "your-sandbase-api-key"
E2B_API_KEY = "your-e2b-api-key"
OUTPUT_DIR = Path("./artifacts")
OUTPUT_DIR.mkdir(exist_ok=True)

# --- 客户端 ---
client = OpenAI(
    base_url="https://api.sandbase.ai/v1",
    api_key=SANDBASE_API_KEY,
)

# --- 步骤 1:解析 Brief → 生成参数 ---
def parse_brief(brief: str) -> dict:
    """用 LLM 将创意 brief 转为结构化生成参数。"""
    response = client.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[
            {"role": "system", "content": """你是创意总监 AI。
将 brief 转为结构化图片生成提示。
输出 JSON:
{
    "prompt": "详细的图片生成提示(英文,描述性)",
    "negative_prompt": "需要避免的内容",
    "aspect_ratio": "16:9 或 1:1 或 9:16",
    "style": "photographic 或 illustration 或 3d-render",
    "analysis_focus": ["color", "composition", "text_readability", "brand_fit"]
}
只输出 JSON。"""},
            {"role": "user", "content": brief}
        ]
    )
    return json.loads(response.choices[0].message.content)

# --- 步骤 2:用 Seedream 生成图片 ---
def generate_image(prompt: str, negative_prompt: str = "",
                   aspect_ratio: str = "16:9") -> str:
    """通过 SandBase 用 Seedream 5 Pro 生成图片。"""
    
    dimensions = {
        "16:9": (1280, 720),
        "1:1": (1024, 1024),
        "9:16": (720, 1280),
    }
    width, height = dimensions.get(aspect_ratio, (1280, 720))
    
    response = client.images.generate(
        model="seedream-5-pro",
        prompt=prompt,
        n=1,
        size=f"{width}x{height}",
        extra_body={"negative_prompt": negative_prompt}
    )
    
    image_url = response.data[0].url
    print(f"✓ 图片已生成:{image_url}")
    return image_url

# --- 步骤 3:写分析代码 ---
def write_analysis_code(image_url: str, analysis_focus: list[str]) -> str:
    """用 LLM 根据关注点写图片分析代码。"""
    
    focus_str = ", ".join(analysis_focus)
    
    response = client.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[
            {"role": "system", "content": f"""你是图片分析 Python 开发者。
写一个完整的 Python 脚本:
1. 从提供的 URL 下载图片
2. 分析:{focus_str}
3. 产出 JSON 格式的结构化结果

要求:
- 用 PIL/Pillow 做图片分析
- 用 numpy 做数值计算
- 用 httpx 下载图片
- 将最终 JSON 结果 print 到 stdout
- 包含色彩分布(前 5 主色 hex 值)
- 包含基本构图指标(三分法对齐)
- 包含亮度/对比度统计
- 优雅处理错误

脚本必须自包含、可直接执行。
只输出 Python 代码,不要 markdown 围栏。"""},
            {"role": "user", "content": f"分析图片 URL:{image_url}"}
        ]
    )
    
    code = response.choices[0].message.content
    if code.startswith("```"):
        code = code.split("\n", 1)[1].rsplit("```", 1)[0]
    return code

# --- 步骤 4:在 E2B 沙盒执行 ---
def execute_in_sandbox(code: str) -> dict:
    """在 E2B 沙盒中运行分析代码并返回结果。"""
    
    sandbox = Sandbox(api_key=E2B_API_KEY)
    
    try:
        # 安装依赖
        sandbox.commands.run("pip install Pillow numpy httpx colorthief", timeout=30)
        
        # 写入并执行脚本
        sandbox.files.write("/home/user/analyze.py", code)
        result = sandbox.commands.run("python /home/user/analyze.py", timeout=60)
        
        if result.exit_code != 0:
            print(f"⚠ 沙盒执行错误:{result.stderr}")
            return {"status": "error", "error": result.stderr, "stdout": result.stdout}
        
        try:
            analysis = json.loads(result.stdout)
            print("✓ 分析完成")
            return {"status": "success", "analysis": analysis}
        except json.JSONDecodeError:
            return {"status": "partial", "raw_output": result.stdout}
    finally:
        sandbox.kill()

# --- 步骤 5:产出报告 Artifact ---
def generate_report(brief: str, params: dict, image_url: str,
                    analysis: dict) -> str:
    """用 LLM 从所有组件综合最终报告。"""
    
    response = client.chat.completions.create(
        model="gpt-4.1",
        messages=[
            {"role": "system", "content": """你是创意分析 AI。
产出 Markdown 格式的专业报告 Artifact:
1. 执行摘要
2. Brief 解读
3. 生成图片引用
4. 技术分析结果(来自代码执行)
5. 迭代建议
6. 成本明细

要具体、可操作。引用分析中的实际数字。"""},
            {"role": "user", "content": f"""
创意 Brief:{brief}

生成参数:
{json.dumps(params, indent=2, ensure_ascii=False)}

图片 URL:{image_url}

代码分析结果:
{json.dumps(analysis, indent=2, ensure_ascii=False)}

产出最终报告 Artifact。"""}
        ]
    )
    
    return response.choices[0].message.content

# --- 编排器 ---
def run_multimodal_agent(brief: str) -> Path:
    """运行完整多模态 Agent 管道。"""
    
    print(f"\n{'='*60}")
    print(f"🎨 多模态 Agent — 处理 Brief")
    print(f"{'='*60}")
    print(f"Brief:{brief}\n")
    
    # 步骤 1:解析 brief
    print("📋 步骤 1:解析 brief...")
    params = parse_brief(brief)
    print(f"   提示词:{params['prompt'][:60]}...")
    print(f"   比例:{params['aspect_ratio']}")
    print(f"   分析焦点:{params['analysis_focus']}")
    
    # 步骤 2:生成图片
    print("\n🖼️  步骤 2:用 Seedream 5 Pro 生成图片...")
    image_url = generate_image(
        prompt=params["prompt"],
        negative_prompt=params.get("negative_prompt", ""),
        aspect_ratio=params.get("aspect_ratio", "16:9")
    )
    
    # 步骤 3:写分析代码
    print("\n💻 步骤 3:写分析代码...")
    code = write_analysis_code(image_url, params["analysis_focus"])
    print(f"   生成 {len(code.split(chr(10)))} 行 Python")
    
    # 步骤 4:沙盒执行
    print("\n🔒 步骤 4:在 E2B 沙盒执行...")
    sandbox_result = execute_in_sandbox(code)
    
    if sandbox_result["status"] == "error":
        print(f"   ⚠ 执行失败,尝试修复...")
        # 自修正:让 LLM 根据错误修复代码
        fix_response = client.chat.completions.create(
            model="gpt-4.1-mini",
            messages=[
                {"role": "system", "content": "修复此 Python 脚本。错误是:"
                 + sandbox_result.get("error", "unknown")},
                {"role": "user", "content": code}
            ]
        )
        fixed_code = fix_response.choices[0].message.content
        if fixed_code.startswith("```"):
            fixed_code = fixed_code.split("\n", 1)[1].rsplit("```", 1)[0]
        sandbox_result = execute_in_sandbox(fixed_code)
    
    # 步骤 5:生成报告
    print("\n📊 步骤 5:生成报告 Artifact...")
    report = generate_report(brief, params, image_url, sandbox_result)
    
    # 保存 Artifact
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    artifact_path = OUTPUT_DIR / f"report_{timestamp}.md"
    artifact_path.write_text(report)
    
    code_path = OUTPUT_DIR / f"analysis_{timestamp}.py"
    code_path.write_text(code)
    
    print(f"\n{'='*60}")
    print(f"✅ Artifact 已保存:{artifact_path}")
    print(f"   分析代码:{code_path}")
    print(f"   图片:{image_url}")
    print(f"{'='*60}\n")
    
    return artifact_path

# --- 成本追踪 ---
def estimate_pipeline_cost() -> dict:
    """估算一次完整管道运行的成本。"""
    return {
        "Brief 解析 (GPT-4.1-mini)": "$0.002",
        "图片生成 (Seedream 5 Pro)": "$0.03",
        "代码编写 (GPT-4.1-mini)": "$0.003",
        "沙盒执行 (E2B)": "$0.005",
        "报告综合 (GPT-4.1)": "$0.015",
        "总计估算": "$0.055"
    }

# --- 主函数 ---
if __name__ == "__main__":
    briefs = [
        "为高端智能手机发布会创建主视觉。手机悬浮效果配戏剧性灯光。"
        "目标受众:科技爱好者 25-40 岁。品牌色:深蓝和银色。",
        
        "设计夏日咖啡系列的社媒 Banner。生活方式感,暖色调,户外咖啡馆场景。"
        "需要同时适用 16:9 和 1:1 裁切。",
    ]
    
    artifact = run_multimodal_agent(briefs[0])
    
    print("\n💰 成本明细:")
    for item, cost in estimate_pipeline_cost().items():
        print(f"   {item}{cost}")

生态组合的工作方式

这个 Agent 使用三种不同能力类型,全部通过 SandBase:

1. LLM 推理(GPT-4.1-mini / GPT-4.1)

client.chat.completions.create(model="gpt-4.1-mini", ...)

用于:brief 解析、代码生成、报告综合。

2. 图片生成(Seedream 5 Pro)

client.images.generate(model="seedream-5-pro", ...)

用于:从提示词创建视觉资产。

关于 SandBase 上可用的图片生成 API,包括 Seedream、Qwen Image 等。

3. 代码执行(E2B 沙盒)

sandbox = Sandbox(api_key=E2B_API_KEY)
sandbox.commands.run("python analyze.py")

用于:安全运行不受信任的分析代码。

Agent 决定生成什么分析什么怎么呈现结果。平台提供能力。这种分离是生态组合的核心。

自修正模式

注意步骤 4 的错误处理:

if sandbox_result["status"] == "error":
    # 让 LLM 根据错误消息修复代码
    fix_response = client.chat.completions.create(...)
    fixed_code = fix_response.choices[0].message.content
    sandbox_result = execute_in_sandbox(fixed_code)

这是”生成 → 执行 → 修复 → 重执行”循环,让 Agent 比静态管道更强大。LLM 看到沙盒执行的实际错误并调整。实践中这能捕获:

  • 导入错误(缺包 → 加 pip install)
  • URL 访问问题(超时 → 加重试逻辑)
  • 数据格式不匹配(意外图片格式 → 加转换)

成本分析

每次完整管道运行:

步骤模型/服务估算成本
Brief 解析GPT-4.1-mini (~800 输入, 200 输出)$0.002
图片生成Seedream 5 Pro (1 张)$0.03
代码编写GPT-4.1-mini (~500 输入, 1000 输出)$0.003
沙盒执行E2B (~30s 运行时)$0.005
报告综合GPT-4.1 (~3000 输入, 800 输出)$0.015
总计~$0.055

规模化:

10 个 brief/天:$0.55/天 → $16.50/月
50 个 brief/天:$2.75/天 → $82.50/月
200 个 brief/天:$11/天 → $330/月

对比人类创意分析师:$80–150/小时。一个 brief 分析手动需 30–60 分钟。Agent 不到 2 分钟完成,成本 $0.055。

扩展到视频

同样的模式适用于视频生成——只需替换步骤 2:

def generate_video(prompt: str) -> str:
    """通过 SandBase 用 Kling 或 MiniMax 生成视频。"""
    # 视频生成是 async(需 30-120s)
    response = client.chat.completions.create(
        model="kling-video-3-standard",
        messages=[{"role": "user", "content": json.dumps({
            "prompt": prompt,
            "duration": 5,
            "aspect_ratio": "16:9"
        })}],
        extra_body={"sandbase_api": "kling/video/generation"}
    )
    # 轮询等待完成...
    return video_url

详细的视频生成 Agent 教程见广告创意 Agent 指南

生产模式

批量处理

import asyncio

async def process_batch(briefs: list[str]) -> list[Path]:
    """并发处理多个 brief。"""
    tasks = [asyncio.to_thread(run_multimodal_agent, brief) for brief in briefs]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return [r for r in results if isinstance(r, Path)]

Artifact 版本管理

class ArtifactStore:
    def __init__(self, base_dir: Path):
        self.base_dir = base_dir
    
    def save(self, brief_id: str, version: int, report: str,
             image_url: str, code: str) -> Path:
        artifact_dir = self.base_dir / brief_id / f"v{version}"
        artifact_dir.mkdir(parents=True, exist_ok=True)
        
        (artifact_dir / "report.md").write_text(report)
        (artifact_dir / "analysis.py").write_text(code)
        (artifact_dir / "metadata.json").write_text(json.dumps({
            "image_url": image_url,
            "timestamp": datetime.now().isoformat(),
            "version": version
        }))
        return artifact_dir

人在环中迭代

def iterate_with_feedback(brief: str, feedback: str,
                          previous_report: str) -> Path:
    """接入人类反馈重新运行 Agent。"""
    enhanced_brief = f"""
原始 brief:{brief}
上一版输出摘要:{previous_report[:500]}
人类反馈:{feedback}
生成改进版本。
"""
    return run_multimodal_agent(enhanced_brief)

展示的关键模式

  1. 生态组合: 一个 Agent 用 LLM + 图片生成 + 代码沙盒。无需分别集成。
  2. 自修正: Agent 用沙盒反馈修复自己的代码错误。
  3. Artifact 产出: 输出是结构化文档,不只是文本——包含引用、分析和建议。
  4. 成本可预测: 每步成本已知。总管道有界可追踪。
  5. 能力分离: Agent 决定做什么。平台提供怎么做。见自主 Agent 最佳模型的模型选择指导。

这个模式可扩展到任何组合 生成 + 分析 + 执行 的工作流。把”图片”替换为”视频”、“文档”或”数据可视化”,架构保持不变。