mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-09 05:50:44 +08:00
- Resolve legacy multimodal inputs from session history when the user sends text-only (assistant images first, then user uploads); optional env toggles. - Support relay_pointer image resolution in legacy lane collector. - Align uvicorn WebSocket frame limit with MAX_PAYLOAD_BYTES; document OCLAW_UVICORN_WS_MAX_SIZE and compatible-mode env knobs. - Admin chat: encode attachments after bubble preview; FileReader-based base64 for large files. - Tests and docs for new behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
6.2 KiB
6.2 KiB
图片专家(Chat UI)专用链路
本文描述 Admin /chat 选择「图片」专家 时的端到端路径。这是一条 与通用 Responses / 主对话模型环路隔离 的特殊分支:仅在 skill_binding_role == "image" 时进入,其它专家或综合模式不受影响。
与本文无关:
docs/GATEWAY_IMAGE_GENERATE.md(网关 RPCimage.generate)、OCR 工具使用的image_ocr_client等。
1. 触发条件与隔离边界
| 条件 | 说明 |
|---|---|
| UI / Gateway | 用户在前端选择专家 image,请求体携带 skill_binding_role(或等价字段)为 image。 |
| 入口守卫 | runtime/direct_loop.py 中 _maybe_image_specialist_legacy_gateway_turn:仅当 skill_binding_role.lower() == "image" 且未设置禁用开关时执行;否则返回 None,后续仍走常规 run_oclaw_direct_loop。 |
| 禁用开关 | AIA_IMAGE_SPECIALIST_DISABLE_LEGACY_GATEWAY_LANE=1:关闭本 Early Return,图片专家改走与普通会话相同的模型/传输栈(用于调试或迁移)。 |
不要在本链路外混用:DashScope 形态的多模态 HTTP、qwen-image* 的空兼容响应回退等,均封装在 platform/llm/image_legacy_client.py 与 image_http_common.py,避免改到 openai_responses 的通用逻辑。
2. 运行时数据流(网关 → 落库)
run_oclaw_direct_loop在用户消息落库后立刻调用_maybe_image_specialist_legacy_gateway_turn。- 输入附件:
collect_legacy_lane_images_from_attachments将 UI 附件规范为data:URL 或 HTTP URL(image_ref/input_image/image_url/relay_pointer等)。若本轮无可用图且未关闭AIA_IMAGE_SPECIALIST_SESSION_IMAGE_FALLBACK,则collect_legacy_lane_images_with_session_fallback按「最近一条带图的助手消息 → 更早的用户上传」从落库历史中补齐。非 compatible 的 native 网关:messages[0].content为 DashScope 文档形态(若干{"image": …}+{"text": …})。compatible-mode/v1默认改为 OpenAI 形状(每条含type:image_url/text),否则上游常报缺少content[n].type;仅当网关明确要求无type的旧形态时设AIA_IMAGE_EXPERT_COMPAT_USE_DASHSCOPE_NATIVE_BLOCKS=1。 - 仍无图(本轮与历史均未解析出输入图):直接写入一条
assistant/assistant_text提示语并返回,不调用上游。 - 有图:调用
send_legacy_image_messages(/chat/completions兼容路径,非 Responses API)。 - 输出解析:
legacy_image_turn_bundle- 文本可为空;若有生成图则
materialize_legacy_response_output_attachments写入本地 blob,产出image_ref(或退化为image_url)。
- 文本可为空;若有生成图则
- 占位文案:成功但只有图、无模型正文时,由
legacy_image_assistant_body_with_placeholder(image_legacy_client)写入中英文占位句;网关与specialist_agent共用,避免两处字符串分叉。 - 持久化:
store.add_message(role=assistant, event_type=assistant_text, attachments=…)—— 附件以 JSON 形式挂在助手消息上,而非 tool 行。
3. 与其它入口的差异
| 场景 | 模块 | 说明 |
|---|---|---|
| Chat 网关 + 图片专家 | direct_loop._maybe_image_specialist_legacy_gateway_turn |
上文主路径;Early Return,不进主 LLM 循环。 |
| Specialist 编排临时会话 | runtime/agents/specialist_agent.py |
同样调用 send_legacy_image_messages / legacy_image_turn_bundle,逻辑对齐但不经过同一 Early Return。 |
两处共用 platform/llm/image_legacy_client.py,避免分叉实现。
4. 鉴权与下载(严格 ACL)
助手消息上的 image_ref 需在 attachment_acl 中有记录,才能在 AIA_ATTACHMENT_ACL_STRICT=1 下通过 GET /admin/api/chat/attachments/{id}。
SqliteStore.add_message会在落库后根据会话ui_session_owner对引用型附件执行link_attachment_acl(与 tool 结果路径一致)。- 历史数据可用
POST /admin/api/chat/admin/attachments/acl/backfill(管理员)补齐。详见docs/attachment-acl.md。
5. WebSocket 收口与前端展示
interfaces/ws/turn_runner.py:final_msg从最近一条非空助手消息组装;_persisted_chat_attachments_nonempty需识别 JSON 数组或单个 JSON 对象,否则纯附件回合会选错行。interfaces/admin/static/chat.js:聚合气泡_buildAggregatedAssistantBubble须对assistant_text片段调用renderAttachmentsEl(不仅tool_result),否则会出现「只有配文、无图」的现象。
6. 环境变量(索引)
详细列表与默认值以 docs/ENVIRONMENT_VARIABLES.md 为准。与本链路相关的典型前缀:
AIA_IMAGE_EXPERT_*/AIA_IMAGE_SPECIALIST_*:图片专家 HTTP 基址、端点、模型、请求扩展等(与AIA_OCR_*分离)。AIA_IMAGE_SPECIALIST_DISABLE_LEGACY_GATEWAY_LANE:禁用网关侧 legacy 专用线。AIA_ATTACHMENT_ACL_STRICT:附件下载是否仅信任 ACL。
7. 测试与回归
tests/test_image_legacy_gateway_lane.py:legacy 解析与规范化。tests/test_attachment_acl_backfill.py:严格 ACL 下助手附件与 ACL 写入。- 修改
chat.js聚合或turn_runnerfinal 消息逻辑后,应用图片专家跑一轮 生成图 + 刷新历史 做冒烟。
8. 变更原则(避免波及其它链路)
- 默认改动范围:
image_legacy_client.py、image_http_common.py、direct_loop中_maybe_image_specialist_*函数体、specialist_agent中与 legacy image 调用相邻代码、turn_runner/chat.js中与 assistant + attachments 展示相邻逻辑。 - 勿在
openai_responses.py中为图片专家单独分支,除非明确要做「非 legacy」通用能力。 - 新增开关优先
AIA_IMAGE_*/AIA_IMAGE_SPECIALIST_*,勿复用 OCR 变量。 - UI 层附件渲染:assistant_text 与 tool_result 对称处理引用型附件,避免只修一端。