优化: AI Chat全栈多批审查修复与架构清理(risk_level清理/路由解耦/工具渲染/测试补测/死代码)

This commit is contained in:
2026-06-18 22:57:19 +08:00
parent 0ca5d9805f
commit a2871a66e0
87 changed files with 5720 additions and 3012 deletions

View File

@@ -7,6 +7,27 @@
---
> ## ⚠️ 实施状态2026-06-18 核对:阶段 1-2 已落地,数据模型形态偏离设计)
>
> **阶段 1数据模型+ 阶段 2provider 适配)已落地**,阶段 3前端+ 阶段 5F-06 联动)未做。
>
> **关键偏离:本文档 §2.1/§2.3 设计「`content: Vec<ContentPart>`」,实际落地改为「`content: String` + `parts: Option<Vec<ContentPart>>`」**`crates/df-ai-core/src/provider.rs:97/105-106`)。
> - 落地理由(见 `provider.rs:44-51` 注释未接入多模态的调用方audit/title/commands/knowledge_inject 等读 `content` 当字符串零回归避免一次性改全仓。content 字段始终保留人类可读文本,多模态片挂在 parts。
> - 后果:本文档 §2.2`deserialize_content` String→单 Text 片、§2.3(构造器签名 `impl Into<String>` 改 `Vec`、§2.4`content_text()` 辅助、§2.5`truncate_for_persist` 改 Vec描述均**不适用**——实际未改 content 类型truncate 仍作用 String content老调用点零改动。
> - 实际辅助方法:`provider.rs:157` `user_parts(content, parts)`、`:162` `has_image()`、`:173` `flattened_parts()`content 前置 Text 片 + parts 追加,供 provider 生成 blocks
>
> **已落地项grep 佐证)**
> - `ContentPart` enum`provider.rs:51-91`Text/Image 两变体,含 `text()`/`image_base64()`/`image_url()`/`is_image()` 构造与判定)。
> - **token 预算修正**`crates/df-ai/src/context.rs:49-67` `estimate_message` 已把 parts 的 Image.base64 / Text.text 同 chars_ratio 计入(此前只算 content 致含图消息 token 严重低估 → build_for_request 误判未超预算 → provider 超限 400/500。注意 `context.rs:57-58` 标注 0.35 比例偏高CR-260618-11#2偏保守致含图消息高估、过度裁剪本次未改值仅标注。
> - **provider 转换**OpenAI 兼容 `crates/df-ai/src/openai_compat.rs:331-358`has_image 走 `flattened_parts` → text/image_url 数组纯文本走字符串简写零回归Anthropic 兼容 `crates/df-ai/src/anthropic_compat.rs:344-372`Image → `source.base64 + media_type`Anthropic 不接受 URL 直传的设计约束落地)。
>
> **未做项**
> - 阶段 3 前端(`src/api/types.ts` ContentPart 类型对齐 / AiChat.vue 粘贴拖拽渲染 / store sendMessage payload—— 未做。
> - 阶段 5 F-06 联动(`commands/project.rs:509-543` extract_description_via_llm 消费 `sample.images` 喂 ContentPart::Image—— 未做,仍走纯文本 prompt对齐 §7 注「没图也能跑纯文本降级」)。
> - 阶段 4 vision 路由F-01 已落地,但 F-01 §6.1 路由已去 cost/intel 硬过滤B-260618-03vision 路由仍可按 `TaskRequirements.modalities=[Vision]` + `has_image()` 筛选候选模型,设计方向不变。
---
## 0. 摘要
`ChatMessage.content: String` 升级为 `Vec<ContentPart>{Text/Image}`,打通「前端粘贴/拖拽图片 → base64 上行 → OpenAI/Anthropic 兼容端点的 image_url/image blocks」全链路并在 provider 转换层对非 vision 模型做文本降级。Phase 1F-01 `ModelCapability`)落地后,由 `ModelRouter``has_image` 自动路由到带 vision 能力的模型F-05 自身可在 F-01 未落地时先做「provider 静态白名单探测」独立跑通,最后接 F-01。同步解锁 F-06`scan.rs::ImageRef` 现仅采集 alt+srcPhase 2 后可由 commands 层读 base64 喂 vision 抽 description。