Files
EPEEAIKit/.cursor/changelog/changelog-full.md

43 KiB
Raw Blame History

Dev Changelog — Full

完整的开发改动记录,按时间倒序排列。作为主动 RAG 的数据源,用户手动唤醒时读取。

记录

[CL-20260413-2320] 2026-04-13 23:20 — 集成 Mem0 记忆系统:滑动窗口 + 跨会话长期记忆

  • tags: Mem0, 记忆系统, 上下文管理, 长期记忆, Ollama, embedding, 滑动窗口
  • affected_files:
    • art-agent/backend/app/memory.py新建
    • art-agent/backend/app/agent/loop.py
    • art-agent/backend/app/config.py
    • art-agent/backend/app/api/chat.py
    • art-agent/backend/requirements.txt
    • art-agent/backend/.env
    • art-agent/frontend/src/lib/api.ts
    • art-agent/frontend/src/app/page.tsx
    • .gitignore
  • what: 集成 Mem0 开源版作为统一记忆方案,一次性解决两个延期方案:上下文管理(滑动窗口截断)和跨会话长期记忆(事实提取+语义检索)
  • why: 当前对话全量透传无截断,长对话会超 token 上限且费用线性增长;且每次会话从零开始无法记住用户偏好
  • decisions:
    • 选择 Mem0 OSS 自部署(非平台托管),完全本地化,数据在 ./data/qdrant
    • DeepSeek 作为事实提取 LLM复用现有 key成本极低
    • Ollama nomic-embed-text 作为本地 embedding免费768维性能足够
    • 不做静默降级Ollama 不可用 → 阻止启动search 失败 → SSE error 中断对话add 失败 → SSE warning 告知用户
    • 用 asyncio.run_in_executor 异步执行 memory.add(),不阻塞用户体验
  • notes:
    • 测试时创建了 data/qdrant 目录(含测试记忆数据),已加入 .gitignore
    • Ollama 需要作为后台服务保持运行
    • 首次 Mem0 初始化约需 5-8 秒(创建 Qdrant collection
    • 解决了延期方案 [context-window-management] 和 [mem0-long-term-memory]
  • source_chat: Mem0 记忆系统集成

[CL-20260413-1130] 2026-04-13 11:30 — 修复 SDXL 模型 404 错误:补全 Replicate 版本 hash

  • tags: bug修复, Replicate, SDXL, 模型配置, 404
  • affected_files:
    • art-agent/backend/app/config.py
  • what: 修复 Stable Diffusion XL 模型调用 Replicate API 返回 404 的问题
  • why: 与之前 Kolors IP-AdapterCL-20260413-0440完全相同的根因——Replicate 对非 Black Forest Labs 官方模型需要 owner/model:version_hash 完整格式,短格式 stability-ai/sdxl 无法定位到具体版本
  • decisions: 使用 Replicate 官方文档中的最新推荐版本 hash 39ed52f2...e08b
  • notes: Flux 系列black-forest-labs/flux-schnell、flux-dev不受此问题影响Replicate 对其支持短格式。后续新增模型时应默认使用完整的 owner/model:version_hash 格式

[CL-20260413-1100] 2026-04-13 11:00 — 修复切换模型后 LLM 仍声称使用旧模型名

  • tags: Agent Loop, system prompt, 模型选择, LLM 幻觉, 模型名
  • affected_files:
    • art-agent/backend/app/agent/loop.py
  • what: System Prompt 中动态注入当前生图模型名称,防止 LLM 从对话历史幻觉旧模型名
  • why: 用户在同一会话内切换模型(如从 InstantStyle 切到 KolorsLLM 在回复中仍声称使用旧模型。根因是 System Prompt 不包含模型信息LLM 从对话历史中的工具返回结果/文字记录推断模型名,导致幻觉
  • decisions: 在 system prompt 末尾动态拼接当前模型名 + 强调忽略旧记录。同时在假生成重试的纠正消息中也附带模型名
  • notes: 通过 debug 日志验证前端→后端→工具执行的模型传递链路完全正确kolors-ipadapter 一路贯穿),问题仅在 LLM 文字输出层面。修复后验证通过

[CL-20260413-1030] 2026-04-13 10:30 — Agent Loop 假生成检测 + 自动重试机制

  • tags: Agent Loop, DeepSeek, function calling, 防幻觉, 自动修复
  • affected_files:
    • art-agent/backend/app/agent/loop.py
  • what: 当 LLM 返回纯文字(无 tool_calls但内容包含"已生成"等模拟生图关键词时,自动注入纠正消息强制 LLM 重新调用工具
  • why: DeepSeek 即使在 System Prompt 中明确禁止模拟工具调用CL-0930仍会在复杂多步任务中用文字"扮演"生图过程,导致前端收不到 image_result 事件。Prompt 约束对 DeepSeek 无效,必须在代码层面硬性拦截
  • decisions: 用正则匹配"已生成"、"生成完成"、"图片已"等关键词,命中 2 次以上且文本 >= 50 字时判定为假生成。检测到后将 LLM 的回复保留在历史中,追加一条纠正消息"你没有调用工具,请立即调用",然后 continue 回到循环让 LLM 重试。重试消耗一次迭代配额,不影响正常对话
  • notes: 此机制主要针对 DeepSeek 的 function calling 纪律问题。GPT-4o 等模型通常不会触发。如果 DeepSeek 重试后仍然不调用工具,会在 max_iterations 用尽后正常结束

[CL-20260413-1000] 2026-04-13 10:00 — 助手消息气泡添加复制文本按钮

  • tags: 前端, UX, chat-messages, 复制
  • affected_files:
    • art-agent/frontend/src/components/chat/chat-messages.tsx
  • what: 助手回复气泡下方新增复制文本按钮hover 时显示,点击复制文本内容并显示对勾反馈
  • why: LLM 生成的 prompt 思路、风格描述等文字内容用户经常需要复制,之前只能手动选中
  • decisions: 按钮放在气泡下方左侧而非内部,避免干扰阅读。只对 assistant 消息显示(用户自己的消息不需要复制)。使用 navigator.clipboard APIhover 显示 + 1.5s 对勾反馈
  • notes: 仅复制纯文本内容,不含图片信息

[CL-20260413-0930] 2026-04-13 09:30 — System Prompt 加入"禁止模拟工具调用"约束

  • tags: prompt 工程, system prompt, DeepSeek, function calling, 防幻觉
  • affected_files:
    • art-agent/backend/app/agent/loop.py
  • what: System Prompt 注意事项中新增"禁止模拟工具调用"硬性约束
  • why: DeepSeek 在复杂多步任务(如一次生成 3 种不同建筑)中,有时不通过 function calling 调用 generate_image 工具,而是用文字"模拟"生成过程(如"已生成"),导致 Agent Loop 第一轮就因 tool_calls_data 为空而 yield done前端收不到 image_result 事件,用户看不到图片
  • decisions: 在 System Prompt 中加一条行为红线,告诉 LLM 必须实际调用工具。轻量级防御(检测文字中包含"已生成"但无工具调用时发警告)暂不实现,先观察 prompt 约束的效果
  • notes: 这是 DeepSeek function calling 纪律问题GPT-4o 等模型通常不会出现。如果 prompt 约束不够,后续可加检测机制

[CL-20260413-0900] 2026-04-13 09:00 — 非 vision + 参考图场景:尊重用户主动指定的风格意图

  • tags: prompt 工程, IP-Adapter, 风格, system prompt, UX
  • affected_files:
    • art-agent/backend/app/agent/loop.py
  • what: 将"绝对禁止风格关键词"改为"不自行猜测,但保留用户明确指定的风格"
  • why: 之前的 system prompt 和非 vision hint 中对风格关键词的禁止是绝对性的("绝对不要"、"不要添加任何"),导致 LLM 在用户主动输入了风格描述(如"赛博朋克风"、"水彩风")时也会丢弃用户意图。系统不应替用户做决定
  • decisions: 措辞从"绝对禁止"改为"不自行猜测,但用户明确指定则保留"。两处同步修改SYSTEM_PROMPT 第 47 行 + 非 vision 模型的 hint 文本。IP-Adapter 风格迁移与用户文字风格描述可叠加不冲突
  • notes: 这是对 CL-20260413-0540 策略的修正——当时为了防止 DeepSeek 脑补画风而加了绝对禁止,现在细化为区分 LLM 猜测 vs 用户意图

[CL-20260413-0800] 2026-04-13 08:00 — 修复 InstantStyle ReadTimeout + 多次生成丢失参考图

  • tags: bug修复, Replicate, InstantStyle, timeout, 参考图, Agent Loop, wait, SDK
  • affected_files:
    • art-agent/backend/app/services/image_gen.py
    • art-agent/backend/app/agent/loop.py
  • what: 修复 InstantStyle 首次调用 ReadTimeout (61.4s) + 后续调用丢失参考图返回 "No input, Save money"
  • why: 两个运行时日志证实的独立问题:(1) wait=60 时 SDK _create_prediction_timeout 生成 httpx.Timeout(5.0, read=60.5) 作为 per-request timeout 传给 httpx.AsyncClient.request(),优先级高于客户端级 300s timeout(2) 成功生成后执行 ref_image_url = None,但 LLM 可能在后续轮次继续调用工具,此时 InstantStyle 因没有 style_image 返回 "No input, Save money"
  • decisions: (1) wait=60wait=False:不发 Prefer: wait headercreate 请求立即返回 prediction IDSDK 自动进入 prediction.async_wait() 轮询路径。轮询请求不带 per-request timeout使用客户端级 read=300s。代价:比 Prefer: wait 模式多几秒轮询延迟,但绝不会 timeout。(2) 完全移除 ref_image_url = None:消息构建(附加参考图到 LLM 消息在外层循环前一次性完成不受影响。ref_image_url 只在 execute_tool() 中使用,整个对话期间都应该传递
  • notes: 迭代了 CL-0700 和 CL-0730 的方案。wait 参数完整语义:True = Prefer: wait + read=60.5sint(n) = Prefer: wait={n} + read={n+0.5}sn 必须 1-60False = 不等待、纯轮询。对慢模型InstantStyle ~128s配合大 payload1.6MB base64wait=False 是唯一可靠选项

[CL-20260413-0730] 2026-04-13 07:30 — 修复生图失败后 LLM 重试丢失参考图

  • tags: bug修复, Agent Loop, 参考图, InstantStyle, ref_image_url
  • affected_files:
    • art-agent/backend/app/agent/loop.py
  • what: 修复 LLM 第一次生图工具调用失败后重试时参考图丢失InstantStyle 返回 "No input, Save money"
  • why: loop.py 在每轮工具调用循环结束后无条件执行 ref_image_url = None。当第一次调用超时失败后LLM 决定重试,但此时 ref_image_url 已被清空第二次工具调用没有参考图。InstantStyle 模型必须有 style_image 才能工作
  • decisions: 改为条件性清除:在工具调用循环中标记 tc_data["_had_images"] = True,循环结束后检查是否有任何成功产出,只有 any_success 时才清除 ref_image_url。失败时保留参考图供后续重试
  • notes: 这个改动对所有参考图模型生效Kolors、InstantStyle 等。只要本轮所有工具调用都失败了ref_image_url 会一直保留直到某次成功为止

[CL-20260413-0700] 2026-04-13 07:00 — 修复 InstantStyle 生图 422 + ReadTimeoutwait 参数超限与 SDK 内部 timeout 覆盖

  • tags: bug修复, Replicate, InstantStyle, API参数, async_run, Prefer header, timeout
  • affected_files:
    • art-agent/backend/app/services/image_gen.py
  • what: 修复 InstantStyle 生图 422Prefer: wait=x must be 1-60)和后续 ReadTimeout61.4s 超时)
  • why: 上次修超时时将 async_run(wait=300) 设为 300 秒。Replicate SDK 将 int 类型的 wait 值设为 Prefer: wait=300 header → API 返回 422。改为 wait=True 后 SDK 生成内部 httpx.Timeout(read=60.5) 作为请求级 timeout 覆盖了客户端级 300s timeout → 上传 1.6MB base64 style_image + 等待响应超过 60s → ReadTimeout
  • decisions: 最终改为 wait=60API 允许的最大 int 值。SDK 行为:(1) Prefer: wait=60 header合法(2) 内部 timeout read=60.5s 用于初始 create prediction 请求;(3) 60s 内未完成自动 fallback 到 prediction.async_wait() 轮询;(4) 轮询请求用客户端级 httpx.Timeout(read=300s)
  • notes: Replicate SDK wait 参数语义:True = Prefer: wait + read=60.5sint(n) = Prefer: wait={n} + read={n+0.5}sn 必须 1-60False = 不等待。对慢模型用 wait=60 + 长客户端 timeout 是最优组合

[CL-20260413-0630] 2026-04-13 06:30 — 修复 Replicate SDK 不走代理 + 超时:自定义 Client 注入代理和长超时

  • tags: bug修复, Replicate, InstantStyle, 代理, httpx, 超时, 图像生成
  • affected_files:
    • art-agent/backend/app/services/image_gen.py
  • what: 修复 InstantStyle 调用时 ConnectTimeout / ReadTimeout + "URL missing protocol" 连环错误
  • why: Replicate Python SDK 的 _build_httpx_client 显式传入 transport=AsyncHTTPTransport(),导致 httpx 跳过环境变量中的 HTTPS_PROXY 代理配置直连 Replicate API。网络不稳定时直连超时SDK 内部状态异常导致后续请求报 "URL missing protocol"。同时默认 read timeout 30s 不够 InstantStyle 的 ~128s 生成时间
  • decisions: 创建 _make_replicate_client() 工厂函数,从环境变量读取代理并注入到 AsyncHTTPTransport(proxy=...) 中传给 ReplicateClient。read timeout 300s、connect timeout 30s。_download_image 也加了代理和 60s 超时
  • notes: Replicate SDK 的代理绕过是个已知设计缺陷(显式 transport 覆盖了 httpx 的代理自动检测)。此修复对所有通过 _replicate_client 的 Replicate API 调用生效。无代理环境下也兼容(proxy=None 时 httpx 不走代理)

[CL-20260413-0600] 2026-04-13 06:00 — 新增 InstantStyle 模型:强风格迁移选项

  • tags: 模型注册, InstantStyle, 风格迁移, IP-Adapter, 模型配置
  • affected_files:
    • art-agent/backend/app/config.py
  • what: 在模型注册表中新增 InstantStylejyoung105/instant-style),专门做风格分离迁移,与 Kolors IP-Adapter 并列为两个参考图模型选项
  • why: Kolors IP-Adapter 的风格迁移弱(内容+风格+构图混合提取),经调研 InstantStyle 是 Replicate 上风格迁移能力最强的可用模型,能从参考图中分离出纯画风(线条、着色、色调)
  • decisions: 利用现有 supports_ref_image + ref_image_param 抽象机制InstantStyle 的 style_image 参数名通过配置映射,无需修改 _build_input 逻辑。默认 block_mode: "style-only"(只迁移风格不迁移构图),style_strength: 1.0
  • notes: InstantStyle 较贵(~$0.12/次)且慢(~128s适合风格定调阶段使用Kolors 保留为低成本快速测试选项。社区模型需版本 hash

[CL-20260413-0540] 2026-04-13 05:40 — 非 vision LLM + 参考图时禁止猜测风格,避免 prompt 与参考图风格冲突

  • tags: prompt 工程, IP-Adapter, 风格一致性, system prompt, 非vision模型
  • affected_files:
    • art-agent/backend/app/agent/loop.py
  • what: 修改 system prompt 和非 vision 模型的参考图文字提示,明确要求 LLM 不要猜测/指定画风关键词,风格完全交给 IP-Adapter 从参考图提取
  • why: DeepSeek 等非 vision LLM 看不到参考图内容,会根据"2D 游戏"等关键词脑补风格(如 pixel art导致 prompt 中的风格描述与参考图实际风格严重冲突。IP-Adapter 优先服从 prompt 的显式风格指令,参考图的风格影响被稀释
  • decisions: 双重约束——system prompt 中加入"看不到参考图时不猜风格"的通用指引 + 注入的文字提示中用编号列表明确三条规则。保留了 vision 模型路径不变vision 模型能看图,可以写风格词)
  • notes: 这是过渡方案,等切换到 vision LLM如 GPT-4oLLM 可直接看图描述风格,此约束自动失效(走 vision_capable 分支)

[CL-20260413-0520] 2026-04-13 05:20 — 多图生成改为单次 API 调用 + 修复空错误信息

  • tags: 性能优化, Replicate, 速率限制, 错误处理, 模型配置
  • affected_files:
    • art-agent/backend/app/services/image_gen.py
    • art-agent/backend/app/config.py
  • what: 多图生成从 for 循环多次 API 调用改为单次调用(利用模型原生批量参数),同时修复异常 str() 为空时的错误信息丢失
  • why: LLM 传 num_images=3 时会发 3 个独立 API 请求在低余额账户的严格速率限制burst=1下后续请求会被 429 拦截。改为单次调用后只消耗 1 次请求配额。空错误信息([生成失败: ])导致用户无法诊断失败原因
  • decisions: 新增 num_images_param 配置字段Flux 用 num_outputsKolors 用 number_of_images),由 _build_input 统一注入。从 kolors 的 default_params 中移除了硬编码的 number_of_images: 1,改为动态设置
  • notes: 空异常现在显示为 {TypeName}: {repr(e)},确保始终有诊断信息

[CL-20260413-0500] 2026-04-13 05:00 — 生成图片后显示使用的模型名称

  • tags: 模型溯源, SSE, 图片生成, 前端展示
  • affected_files:
    • art-agent/backend/app/services/image_gen.py
    • art-agent/backend/app/agent/tools.py
    • art-agent/backend/app/agent/loop.py
    • art-agent/frontend/src/lib/types.ts
    • art-agent/frontend/src/app/page.tsx
    • art-agent/frontend/src/components/chat/chat-messages.tsx
  • what: 图片生成后在对话中显示实际使用的模型名称(如"由 Kolors IP-Adapter 生成"),失败时也附带模型名称
  • why: 用户无法确认前端选择的模型是否真的被用于生图,特别是在多模型切换场景下需要明确溯源
  • decisions: generate_images 返回值从 list[str] 改为 GenerateResult 数据类(包含 urls + model_name + model_id模型名称通过 SSE image_resulttool_error 事件透传到前端。ChatMessage 类型新增 modelName 可选字段,消息归档后仍可查看模型来源
  • notes: 模型名称来自 config.py 注册表中的 name 字段,所以显示的是友好名称而非 Replicate 的 model_id

[CL-20260413-0440] 2026-04-13 04:40 — 修复 Kolors IP-Adapter 模型 404 错误:补全 Replicate 版本 hash

  • tags: bug修复, Replicate, Kolors, IP-Adapter, 模型配置
  • affected_files:
    • art-agent/backend/app/config.py
  • what: 在 kolors-ipadapter 的 model_id 中补全版本 hashfofr/kolors-with-ipadapter 改为 fofr/kolors-with-ipadapter:5a1a92b2...
  • why: Replicate SDK async_run 对非 official 模型(社区模型)只用 owner/model 格式调用时,会尝试 official model predictions 端点,该端点返回 404。必须使用 owner/model:version_hash 格式才能正确创建 prediction
  • decisions: 只修复 kolors 模型唯一报错的其他三个模型flux-schnell、flux-dev、sdxl均为 official/热门模型,owner/model 格式能正常工作
  • notes: 未来新增社区模型时,需确保 model_id 包含版本 hash。经实测加版本 hash 后生图成功

[CL-20260413-0430] 2026-04-13 04:30 — 图片生成失败时将具体错误信息透传到前端

  • tags: 错误处理, Agent Loop, SSE, 调试体验
  • affected_files:
    • art-agent/backend/app/agent/loop.py
    • art-agent/frontend/src/app/page.tsx
    • art-agent/frontend/src/lib/api.ts
  • what: 新增 tool_error SSE 事件类型,将图片生成工具的具体错误信息(如 Replicate API 报错详情)直接透传到前端展示
  • why: 之前工具调用失败时,错误信息只传回给 LLMLLM 会自行"翻译"错误(如说成"速率限制"),用户无法看到真实报错,排查困难。典型场景:使用 Kolors IP-Adapter 生图失败,前端只看到 LLM 的模糊描述,无法定位是参数错误、超时还是 API 限制
  • decisions: 错误信息同时发给前端展示和 LLM 继续对话,不互斥。前端用 ⚠️ 前缀醒目显示错误详情
  • notes: 此改动不影响 LLM 的重试机制(工具结果仍然回传给 LLM只是额外增加了一条面向用户的 SSE 事件

[CL-20260413-0330] 2026-04-13 03:30 — README 补充访问地址汇总 + 穿透管理文档

  • tags: 文档, README, 穿透, Cloudflare, cloudflared
  • affected_files:
    • art-agent/README.md (新增"访问地址"章节 + 重写"远程访问"章节)
  • what: README 新增三种访问场景(本机/局域网/外网)的地址汇总表,重写远程访问章节补充 cloudflared 安装指引、穿透管理操作表、代理配置排错
  • why: 原 README 远程访问章节过于简略,缺少 cloudflared 安装方式、穿透的启动/停止/排错说明,用户实际操作时需要这些信息
  • decisions:
    • 访问地址章节放在"使用"之后、"配置说明"之前,让用户启动后立即看到访问方式
    • cloudflared 安装提供 winget 和手动下载两种方式winget 安装后可能不在 PATH 中)
    • 穿透管理用表格呈现(启动/停止/查看状态/重启),简洁直观
    • 代理排错放在注意事项中,因为国内环境常需代理才能连上 Cloudflare
  • notes: 无

[CL-20260412-2345] 2026-04-12 23:45 — 参考图上传独立化:进度条 + 状态反馈 + 失败重试

  • tags: 前端, 后端, 参考图, 上传, UX, 进度反馈
  • affected_files:
    • art-agent/backend/app/api/chat.py (新增 POST /api/upload-ref-image 独立上传端点chat 端点新增 ref_image_url 字段)
    • art-agent/frontend/src/lib/api.ts (新增 uploadRefImage 函数XMLHttpRequest 实现进度回调sendChat 参数从 File 改为服务端路径字符串)
    • art-agent/frontend/src/components/chat/chat-input.tsx (重写上传流程选图即上传、环形进度条、状态角标、失败重试、input value 重置)
    • art-agent/frontend/src/app/page.tsx (handleSend 适配新签名:接收服务端路径而非 File标注截图也走独立上传)
  • what: 将参考图从"随消息一起提交"改为"选中后立即独立上传",全程有进度条、状态提示、失败重试入口
  • why: 原方案图片上传绑定在发送消息时才执行,无任何进度反馈。大图或走 Cloudflare Tunnel 时用户完全无法判断上传是否开始、是否成功、是否卡住。多次上传参考图后 file input 不重置也导致交互异常
  • decisions: 使用 XMLHttpRequest 而非 fetchfetch 不支持 upload progress 事件);后端同时保留 ref_image 文件上传和 ref_image_url 路径两种方式,向后兼容
  • notes: 上传超时设为 120 秒;支持 AbortController 取消file input 每次选择后立即重置 value确保同一文件可重复选择

[CL-20260412-2315] 2026-04-12 23:15 — 修复 Cloudflare Tunnel 跨域开发警告

  • tags: 前端, 配置, Next.js, Cloudflare, 跨域
  • affected_files:
    • art-agent/frontend/next.config.ts (新增 allowedDevOrigins)
  • what: 在 next.config.ts 中添加 allowedDevOrigins: ["*.trycloudflare.com"],消除 Cloudflare Tunnel 穿透时的跨域警告
  • why: Next.js 检测到来自 trycloudflare.com 的跨域请求,发出警告提示未来版本将强制要求配置
  • decisions: 使用通配符 *.trycloudflare.com 覆盖所有 Quick Tunnel 随机域名
  • notes: 仅影响开发模式,生产构建不受影响

[CL-20260412-2300] 2026-04-12 23:00 — 集成 Kolors IP-Adapter 模型,参考图可直接用于风格生成

  • tags: 后端, 前端, IP-Adapter, 风格迁移, 参考图, 模型注册, Replicate, 架构
  • affected_files:
    • art-agent/backend/app/config.py (新增 kolors-ipadapter 模型注册 + supports_ref_image / ref_image_param 通用字段)
    • art-agent/backend/app/services/image_gen.py (ReplicateProvider._build_input 支持参考图注入 + to_data_uri 公共工具函数)
    • art-agent/backend/app/agent/loop.py (复用 to_data_uri 替代原 _to_vision_url移除冗余 import)
    • art-agent/frontend/src/lib/types.ts (ImageModelInfo 新增 supports_ref_image 字段)
    • art-agent/frontend/src/components/chat/model-selector.tsx (模型列表中显示"参考图"标记)
  • what: 集成 Kolors IP-Adapter 模型fofr/kolors-with-ipadapter参考图可真正参与图像生成的风格控制架构上为后续切换其他 IP-Adapter 模型预留了通用扩展机制
  • why: 之前参考图仅由 LLM 侧理解(且 DeepSeek 看不到图),生图工具侧完全忽略了参考图。用户希望参考图能真正影响生成结果的风格
  • decisions:
    • 模型注册表新增两个通用字段supports_ref_image布尔标记和 ref_image_param参考图参数名不同模型可能不同
    • _build_input 根据 supports_ref_image 自动走不同构建逻辑,新增 IP-Adapter 模型只需加注册表配置
    • 参考图通过 base64 data URI 传递给 Replicate避免本地 URL 不可达的问题)
    • to_data_uri 抽为 image_gen.py 中的公共函数loop.py 复用(替代原 _to_vision_url
    • Kolors IP-Adapter 默认 ip_adapter_weight=0.8(非 1.0),给 prompt 文字留一些影响空间
    • 前端模型列表中为支持参考图的模型显示绿色"参考图"徽章
    • get_image_models_list 返回 supports_ref_image 字段,前端据此渲染标记
  • notes:
    • Kolors IP-Adapter 成本极低(~$0.004/次),速度快(~4s
    • 后续要换其他 IP-Adapter 模型(如 Flux IP-Adapter v2只需在 IMAGE_MODELS 中新增配置
    • 分层组合产线方案IP-Adapter → LoRA → ControlNet已记录为延期方案 [style-pipeline-layered]

[CL-20260412-2230] 2026-04-12 22:30 — 用户消息气泡中显示参考图缩略图

  • tags: 前端, 参考图, UX, chat-messages
  • affected_files:
    • art-agent/frontend/src/lib/types.ts (ChatMessage 新增 refImageUrl 字段)
    • art-agent/frontend/src/app/page.tsx (构造 userMessage 时保存参考图 Blob URL)
    • art-agent/frontend/src/components/chat/chat-messages.tsx (用户消息气泡中渲染参考图缩略图)
  • what: 用户上传参考图发送后,在聊天气泡中显示参考图缩略图,让用户确认图片确实被附带发送了
  • why: 之前用户上传参考图后,发送消息后气泡中看不到参考图,无法确认是否上传成功,体验不好
  • decisions:
    • 使用 URL.createObjectURL 创建 Blob URL 用于当前会话内显示(轻量、即时)
    • Blob URL 不持久化到 localStorage刷新后失效避免存储 base64 data URI 的空间开销
    • 参考图缩略图显示在消息文本上方,最大尺寸 160×120px
  • notes:
    • Blob URL 仅在当前标签页有效刷新页面后旧消息中的参考图缩略图不可见MVP 可接受)
    • 如需持久化,后续可改为存储后端上传路径(需要等后端返回 upload URL 后再构造 userMessage

[CL-20260412-2200] 2026-04-12 22:00 — 修复 DeepSeek 不支持 image_url 导致参考图上传报错

  • tags: bug修复, 后端, Agent Loop, vision, DeepSeek, 多模态
  • affected_files:
    • art-agent/backend/app/agent/loop.py (新增 vision 能力检测,非 vision 模型走文字提示)
  • what: 修复使用 DeepSeek 作为 LLM 时,上传参考图后报 400 错误 unknown variant 'image_url', expected 'text'
  • why: 代码原本假设所有 LLM 都支持 OpenAI Vision API 的 image_url content type但 DeepSeek 的 Chat API 只支持 text 类型
  • decisions:
    • 通过模型名称关键词检测 vision 能力gpt-4o / gpt-4-vision / claude 视为支持)
    • 不支持 vision 的模型:用文字提示告知 LLM 有参考图存在,参考图仍由图像生成工具侧处理
    • 支持 vision 的模型:保持原有 image_url 格式不变
  • notes:
    • 此方案确保参考图功能在任何 LLM 下都不会报错
    • 非 vision 模型无法"看到"参考图,但生图工具仍会收到参考图用于 img2img 场景
    • 如需更精确的 vision 能力检测,可后续改为在 config.py 中按模型注册 vision 标志

[CL-20260412-2130] 2026-04-12 21:30 — 修复图片生成失败时前端显示破碎图标

  • tags: bug修复, 前端, 后端, 图像生成, 错误处理
  • affected_files:
    • art-agent/backend/app/agent/tools.py (分离有效 URL 和错误信息)
    • art-agent/frontend/src/app/page.tsx (过滤无效 URL空列表时不渲染图片网格)
  • what: 修复 Replicate API 失败时前端出现 4 个破碎图标框的问题
  • why: 用户在 Replicate 余额不足402时生图错误字符串被当作图片 URL 传给 <img> 标签
  • decisions:
    • 后端 tools.py将 generate_images 返回值分为 images有效 URL和 errors错误信息两个字段
    • 前端 page.tsx过滤以 [ 开头的无效 URL无有效图片时直接 break 不创建 ImageAsset
  • notes:

[CL-20260412-2100] 2026-04-12 21:00 — 生图模型动态切换Provider 抽象 + 前端模型选择器

  • tags: 后端, 前端, 图像生成, 模型切换, Provider, 重构, Replicate
  • affected_files:
    • art-agent/backend/app/config.py (新增 IMAGE_MODELS 注册表 + get_image_model_config / get_image_models_list / get_default_image_model_id)
    • art-agent/backend/app/services/image_gen.py (重构ImageProvider 抽象基类 + ReplicateProvider 实现 + generate_images 接受 model_id)
    • art-agent/backend/app/api/chat.py (新增 GET /api/models 端点 + POST /api/chat 增加 image_model 参数)
    • art-agent/backend/app/agent/loop.py (run_agent_loop 增加 image_model 参数透传)
    • art-agent/backend/app/agent/tools.py (execute_tool 增加 image_model 参数透传)
    • art-agent/backend/.env (IMAGE_MODEL 改为短 ID 格式)
    • art-agent/backend/.env.example (同步更新)
    • art-agent/frontend/src/lib/types.ts (新增 ImageModelInfo 类型)
    • art-agent/frontend/src/lib/api.ts (新增 fetchModels() + sendChat 增加 imageModel 参数)
    • art-agent/frontend/src/components/chat/model-selector.tsx (新建:模型选择下拉组件)
    • art-agent/frontend/src/components/chat/chat-input.tsx (集成 ModelSelector + onSend 签名扩展)
    • art-agent/frontend/src/app/page.tsx (handleSend 透传 imageModel 到 sendChat)
  • what: 将图像生成服务从 Replicate 硬绑定重构为 Provider 抽象架构,支持 Replicate 上多模型flux-schnell / flux-dev / SDXL按消息粒度切换
  • why: 用户希望能在对话中随时切换生图模型来对比不同模型的效果
  • decisions:
    • Provider 模式:抽象基类 ImageProvider + 具体实现(当前只有 ReplicateProvider预留 DalleProvider/ComfyUIProvider 等扩展点
    • 模型注册表放在 config.py 中Python dict新增模型只需加一条配置
    • 前端模型列表由后端 API 驱动GET /api/models不在前端硬编码
    • 切换粒度为每条消息级(最灵活),通过 FormData 传递 image_model 参数
    • 模型选择持久化到 localStorage作为后续消息的默认值
    • Flux 系列使用 aspect_ratio 参数SDXL 使用 width/height 参数,由 ReplicateProvider._build_input 内部分流处理
  • notes:
    • 向后兼容image_model 参数可选,不传时使用 .env 中的默认模型
    • .env 中 IMAGE_MODEL 支持短 IDflux-schnell和完整 Replicate IDblack-forest-labs/flux-schnell自动转换

[CL-20260412-1800] 2026-04-12 18:00 — 移动端适配 + Cloudflare Tunnel 内网穿透

  • tags: 前端, 响应式, 移动端, 部署, Cloudflare, 穿透, 配置
  • affected_files:
    • art-agent/frontend/src/app/layout.tsx (viewport meta 配置)
    • art-agent/frontend/src/app/globals.css (iOS bounce 防护、tap highlight、dvh 支持、遮罩动画)
    • art-agent/frontend/src/app/page.tsx (桌面端展开按钮加 hidden md:flex)
    • art-agent/frontend/src/app/gallery/page.tsx (网格 gap/列数适配、hover 操作移动端始终可见、选择框可见)
    • art-agent/frontend/src/components/sidebar/sidebar.tsx (移动端固定定位抽屉 + 遮罩)
    • art-agent/frontend/src/components/layout/top-nav.tsx (新增汉堡菜单按钮、间距微调)
    • art-agent/frontend/src/components/detail/image-detail-panel.tsx (移动端全屏 overlay)
    • art-agent/frontend/src/components/chat/chat-messages.tsx (气泡宽度 90%、间距收紧)
    • art-agent/frontend/src/components/chat/chat-input.tsx (padding 收紧)
    • art-agent/frontend/src/components/chat/image-grid.tsx (max-width 适配、操作栏移动端可见)
    • art-agent/frontend/src/lib/app-context.tsx (小屏默认折叠侧边栏、切换会话自动收起)
    • art-agent/frontend/next.config.ts (trycloudflare.com + replicate.delivery 白名单)
    • art-agent/start-tunnel.ps1 (新建:一键穿透脚本)
    • art-agent/README.md (新增远程访问章节、uvicorn 加 --host 0.0.0.0)
  • what: 为实现手机浏览器远程访问完成移动端响应式适配9 个组件)和 Cloudflare Quick Tunnel 穿透方案
  • why: 用户希望把项目发给自己和朋友在手机上通过浏览器使用
  • decisions:
    • 移动端断点统一用 md: (768px),与 Tailwind 默认保持一致
    • 侧边栏移动端用 fixed + overlay 抽屉模式,桌面端保持原有 w-0/w-[280px] 切换
    • 图片详情面板移动端全屏fixed inset-0不做半屏因为手机屏幕空间有限
    • 穿透方案选 Cloudflare Quick Tunnel免费、免注册不选 ngrok有连接限制
    • 穿透脚本自动管理 .env.local 的更新和恢复,减少手动操作
    • hover 操作在移动端始终显示(无 hover 事件),避免操作不可达
    • 路线 B云服务器正式部署记录为延期方案待后续实施
  • notes:
    • 构建验证通过,无 lint 错误
    • cloudflared 通过 winget 安装,版本 2025.8.1
    • Quick Tunnel 每次启动分配随机域名xxx.trycloudflare.com非固定
    • 穿透启动后需重启前端才能读取新的 NEXT_PUBLIC_API_URL
    • project-launcher Skill 中的 uvicorn 命令也同步加了 --host 0.0.0.0

[CL-20260412-1530] 2026-04-12 15:30 — 修复 .env 配置加载时序问题

  • tags: 后端, bug修复, 配置, dotenv, Python
  • affected_files:
    • art-agent/backend/app/main.py (load_dotenv 前置 + override=True)
    • art-agent/backend/app/config.py (模块级常量 → 函数式懒读取)
    • art-agent/backend/app/agent/loop.py (引用改为函数调用)
    • art-agent/backend/app/services/image_gen.py (引用改为函数调用)
    • art-agent/backend/.env (OPENAI_BASE_URL 去掉 /v1)
  • what: 修复切换 DeepSeek API 后报 "Model Not Exist" 400 错误
  • why: 用户修改 .env 切换到 DeepSeek但实际发出的请求仍使用默认模型名 gpt-4o-mini
  • decisions:
    • load_dotenv(override=True) 放在 main.py 所有业务 import 之前,确保环境变量在任何模块读取前就位
    • config.py 从模块级常量改为函数get_llm_model() 等),避免 import 时求值被固化
    • 不使用 lru_cache避免首次调用在 load_dotenv 前就缓存了空值)
  • notes:
    • 根因有两层import 时序config.py 在 load_dotenv 前被 import+ override 默认行为(不覆盖已有环境变量)
    • 通过在 uvicorn 同环境中运行 Python 脚本成功复现了 API 调通,证明问题在进程内加载顺序而非 API 本身
    • DeepSeek base_url 使用 https://api.deepseek.com不带 /v1与官方文档一致

[CL-20260412-1500] 2026-04-12 15:00 — 品牌重命名 EPEEKit + API 配置集中化

  • tags: EPEEKit, 品牌, 配置, 后端, 前端, 重构
  • affected_files:
    • art-agent/frontend/src/app/layout.tsx (title/description)
    • art-agent/frontend/src/components/layout/top-nav.tsx (Logo SVG + 品牌名)
    • art-agent/frontend/src/app/page.tsx (欢迎文案)
    • art-agent/frontend/src/lib/store.ts (localStorage 键名)
    • art-agent/frontend/src/app/gallery/page.tsx (下载前缀)
    • art-agent/frontend/src/components/detail/image-detail-panel.tsx (下载前缀)
    • art-agent/frontend/src/components/chat/image-grid.tsx (下载前缀)
    • art-agent/frontend/package.json (项目名)
    • art-agent/frontend/package-lock.json (项目名)
    • art-agent/backend/app/main.py (FastAPI title)
    • art-agent/backend/app/config.py (新建:集中配置)
    • art-agent/backend/app/agent/loop.py (引用集中配置)
    • art-agent/backend/app/services/image_gen.py (引用集中配置 + 简化重复分支)
    • art-agent/backend/.env (重组为分组结构 + 新增 LLM_MODEL/IMAGE_MODEL 等)
    • art-agent/backend/.env.example (新建)
    • art-agent/README.md (全文更新)
  • what: 将应用从 "Art Agent" 正式命名为 "EPEEKit",同时将后端所有硬编码的 API/模型配置抽取到 .env 文件,通过 config.py 集中管理
  • why: 用户要求正式命名应用并希望能方便地切换 LLM 和图像生成模型进行测试
  • decisions:
    • 品牌名全部统一为 "EPEEKit"包括页面标题、Logo、下载文件名、localStorage 键名
    • Logo 采用内联 SVG 设计(主题色圆角方块 + A/i 组合),不引入外部图片资源
    • API 配置走 .env + config.py 方案(非 settings.py 类模式),保持极简
    • 切换 LLM 只需改 .env 中 3 个值OPENAI_BASE_URL + OPENAI_API_KEY + LLM_MODEL
    • image_gen.py 中去除了参考图分支的重复代码(两个分支逻辑完全相同)
  • notes:
    • localStorage 键名变更意味着旧数据不会自动迁移MVP 阶段可接受)
    • .env 文件中含真实密钥,需确认 .gitignore 覆盖

[CL-20260412-0300] 2026-04-12 03:00 — 完成交互原型全面重构

  • tags: art-agent, 前端, 交互设计, 三栏布局, 标签系统, Canvas标注, 资源库, 后端
  • affected_files:
    • art-agent/frontend/src/app/page.tsx (重写)
    • art-agent/frontend/src/app/layout.tsx (添加 AppProvider)
    • art-agent/frontend/src/app/globals.css (增加样式)
    • art-agent/frontend/src/app/gallery/page.tsx (新建)
    • art-agent/frontend/src/lib/types.ts (新建:全局类型定义)
    • art-agent/frontend/src/lib/store.ts (新建localStorage 持久化存储)
    • art-agent/frontend/src/lib/app-context.tsx (新建:全局状态 Context)
    • art-agent/frontend/src/lib/api.ts (更新类型兼容)
    • art-agent/frontend/src/components/layout/top-nav.tsx (新建)
    • art-agent/frontend/src/components/sidebar/sidebar.tsx (新建)
    • art-agent/frontend/src/components/sidebar/session-list.tsx (新建)
    • art-agent/frontend/src/components/sidebar/tag-filter.tsx (新建)
    • art-agent/frontend/src/components/chat/chat-messages.tsx (适配新类型)
    • art-agent/frontend/src/components/chat/chat-input.tsx (增加拖拽上传)
    • art-agent/frontend/src/components/chat/image-grid.tsx (增加操作栏)
    • art-agent/frontend/src/components/detail/image-detail-panel.tsx (新建)
    • art-agent/frontend/src/components/detail/annotation-canvas.tsx (新建)
    • art-agent/backend/app/agent/loop.py (System Prompt + base64 转换)
  • what: 从单页对话 MVP 全面重构为完整交互原型,三个 Phase 一次性完成
  • why: 用户要求完整设计交互原型,通过规划讨论确定了三栏布局 + 标签系统 + 标注 + 资源库的完整方案
  • decisions:
    • 数据持久化使用 localStorageMVP 阶段),后续可迁移到后端数据库
    • 全局状态管理使用 React Context + useReducer 模式,不引入第三方状态库
    • 标注功能使用原生 Canvas API不引入第三方画板库减少依赖
    • 标注坐标使用归一化比例0-1与图片实际分辨率解耦
    • 资源库使用 Modal overlay 展示详情,而非独立路由页面
    • 标注截图通过 base64 data URI 直接传给 OpenAI Vision后端自动处理本地路径转换
  • notes:
    • 新增 12 个源文件,修改 6 个现有文件,无新依赖引入
    • 内置标签 6 个UI、Icon、原画、风格探索、立绘、概念图
    • 标注工具 4 种:矩形框选、箭头、自由画笔、文字,含撤销/清除
    • 构建验证通过,无 linter 错误
    • 未来可优化:标签自动推荐逻辑(当前仅预留接口)、后端会话持久化、图片搜索索引

[CL-20260411-1500] 2026-04-11 15:00 — 完成美术 Agent 产品决策和技术选型

  • tags: art-agent, 产品决策, 技术选型, 规划
  • affected_files:
    • docs/art-agent/DECISIONS.md
    • docs/art-agent/TECH-STACK.md
  • what: 通过 5 轮结构化讨论确定了美术 Agent 工具的产品决策产品形态、交互模型、AI 架构、风格管理、资源 Pipeline并完成全部 8 个维度的技术选型
  • why: 项目从零开始,需要先把产品方向和技术基准定下来再动手写代码
  • decisions:
    • 产品形态选 Chat-first Web App排除纯 Bot 和桌面应用)
    • 前端 Next.js / 后端 Python FastAPI / 自建 Agent Loop不用 LangChain
    • 数据库 PostgreSQL / 图像生成 Replicate / 部署 Vercel + Railway
    • 对象存储 MVP 先用本地文件系统
  • notes: 技术选型中图像生成 API、部署方案、异步任务三项用户未明确选定采用了推荐方案

[CL-20260411-1600] 2026-04-11 16:00 — 搭建美术 Agent MVP 全部前后端代码

  • tags: art-agent, MVP, 前端, 后端, FastAPI, Next.js, Agent Loop
  • affected_files:
    • art-agent/README.md
    • art-agent/backend/requirements.txt
    • art-agent/backend/.env.example
    • art-agent/backend/app/main.py
    • art-agent/backend/app/api/chat.py
    • art-agent/backend/app/agent/loop.py
    • art-agent/backend/app/agent/tools.py
    • art-agent/backend/app/services/image_gen.py
    • art-agent/frontend/package.json
    • art-agent/frontend/src/app/page.tsx
    • art-agent/frontend/src/app/layout.tsx
    • art-agent/frontend/src/app/globals.css
    • art-agent/frontend/src/components/chat/chat-messages.tsx
    • art-agent/frontend/src/components/chat/chat-input.tsx
    • art-agent/frontend/src/components/chat/image-grid.tsx
    • art-agent/frontend/src/lib/api.ts
    • docs/art-agent/MVP-PLAN.md
  • what: 从零创建了完整的 MVP 前后端代码,包括 FastAPI 后端Agent Loop + Replicate 图像生成 + SSE 流式推送)和 Next.js 前端Chat UI + 参考图上传 + 图片下载),后端已验证可正常启动
  • why: 以最小流程跑通端到端闭环(对话 → 生图 → 迭代 → 保存),快速暴露集成问题
  • decisions:
    • MVP 范围刻意砍掉:数据库/持久化、Skill/Rules 机制、风格库、用户认证、云端部署
    • Agent Loop 硬编码 system prompt不走 Skill 扩展(最简化)
    • 图像模型选 flux-schnell快速版优先验证流程通畅
    • OpenAI 客户端延迟初始化,避免无 Key 时模块加载失败
  • notes:
    • 前端使用 Tailwind CSS v4 + PostCSS 配置方式(非 tailwind.config.ts
    • 参考图在 MVP 阶段仅通过 GPT vision 理解风格后融入 prompt未直接传给图像模型做 img2img

[CL-20260411-1630] 2026-04-11 16:30 — 完成开发环境搭建和依赖安装

  • tags: art-agent, 环境搭建, Node.js, Python
  • affected_files:
    • art-agent/backend/venv/
    • art-agent/frontend/node_modules/
  • what: 通过 winget 安装 Node.js v24.14.1,创建 Python 虚拟环境并安装后端依赖9 个包),安装前端 npm 依赖46 个包),后端启动验证通过
  • why: 代码写好后需要实际运行环境来验证
  • decisions:
    • Node.js 用 winget 安装 LTS 版本
    • Python 虚拟环境放在 backend/venv/ 下
  • notes:
    • 遇到 3 个环境问题已解决OpenAI 延迟初始化、PowerShell 不支持 &&、脚本执行策略限制
    • 端到端完整测试待用户配置 API Key 后进行