diff --git a/.memory/worklog.json b/.memory/worklog.json
index fe1550e..98fb15d 100644
--- a/.memory/worklog.json
+++ b/.memory/worklog.json
@@ -6,12 +6,6 @@
"ts": "2026-05-20T07:11:44Z",
"type": "session-end"
},
- {
- "files_changed": 2,
- "message": "Claude 会话结束 · 持续 0 秒 · 最近命令:claude · 分支 main · 2 项未提交变更 · 最近提交:auto-save 2026-05-20 15:01 (~2)",
- "ts": "2026-05-20T07:11:44Z",
- "type": "session-end"
- },
{
"files_changed": 2,
"hash": "641b3a2",
@@ -3207,6 +3201,13 @@
"type": "session-heartbeat",
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 2 项未提交变更 · 最近提交:docs: record video error deployment",
"files_changed": 2
+ },
+ {
+ "ts": "2026-05-26T10:00:47+08:00",
+ "type": "commit",
+ "message": "auto-save 2026-05-26 10:00 (~2)",
+ "hash": "c415cd0",
+ "files_changed": 2
}
]
}
diff --git a/api/main.py b/api/main.py
index a666c28..2016c1b 100644
--- a/api/main.py
+++ b/api/main.py
@@ -5271,7 +5271,7 @@ class CreativeCopyResp(BaseModel):
class PromptPolishReq(BaseModel):
text: str
system_prompt: str = ""
- mode: Literal["image", "video", "general"] = "image"
+ mode: Literal["image", "video", "general", "chat"] = "image"
target_language: Literal["en", "zh", "keep"] = "en"
@@ -5421,7 +5421,7 @@ def _prompt_polish_fallback(req: PromptPolishReq) -> PromptPolishResp:
f"{base}. Smooth camera movement, clear subject continuity, stable composition, "
"natural motion, coherent lighting, no subtitles, no watermark."
)
- elif req.mode == "general":
+ elif req.mode in {"general", "chat"}:
polished = base
else:
polished = (
@@ -5448,16 +5448,25 @@ def polish_prompt(req: PromptPolishReq) -> PromptPolishResp:
"image": "an image-generation prompt",
"video": "a video-generation prompt",
"general": "a concise generation prompt",
+ "chat": "a professional response to the user's request",
}.get(req.mode, "an image-generation prompt")
user_system = req.system_prompt.strip()
prompt = (
f"Rewrite the user's input into {mode_hint} in {target_label}.\n"
"Preserve the user's actual subject, brand, product, place, style, and intent.\n"
- "Do not add SKG, health-tech, massage products, TikTok ad framing, product sales language, hashtags, captions, or any brand/product not explicitly present in the input.\n"
+ "Do not add SKG, health-tech, massage products, TikTok ad framing, product sales language, hashtags, captions, or any brand/product not explicitly present in the input or user-selected guidance.\n"
"Do not add medical, wellness, or advertising claims unless the user asked for them.\n"
"Improve concrete visual details, composition, lighting, camera language, materials, mood, and quality.\n"
"Return only the rewritten prompt. No markdown, labels, JSON, quotes, explanation, or alternatives.\n"
)
+ if req.mode == "chat":
+ prompt = (
+ f"Answer or rewrite the user's request professionally in {target_label}.\n"
+ "Follow the user-selected guidance when provided.\n"
+ "Do not add SKG, health-tech, massage products, TikTok ad framing, product sales language, hashtags, captions, or any brand/product not explicitly present in the input or user-selected guidance.\n"
+ "Do not add medical, wellness, or advertising claims unless the user asked for them.\n"
+ "Return only the final content in the format requested by the guidance. No markdown fences, labels, explanation, or alternatives unless explicitly requested.\n"
+ )
if req.mode == "video":
prompt += (
"For video, describe motion, timing, camera movement, continuity, and what changes over time. "
diff --git a/docs/source-analysis.html b/docs/source-analysis.html
index 2f22507..113b039 100644
--- a/docs/source-analysis.html
+++ b/docs/source-analysis.html
@@ -582,8 +582,9 @@
2026-05-25 上游能力恢复版:用户明确要求“API 没关系,其他恢复,别削弱”。因此根域名画布恢复 chatfire-AI/huobao-canvas 的成熟节点和工作流结构:推荐词、AI 润色、自动执行、工作流模板、首帧/尾帧/参考图节点、图片/视频/LLM 配置、多角度分镜、故事板、绘本和批量下载都保留;只继续替换品牌、路由和 API 接入。生成请求仍走 SKG 后端 /api 与登录 Cookie,员工不需要个人 API Key。
2026-05-25 媒体模型接入收口:图片和视频模型选择只暴露当前后端真实可用项:图片为 auto、gpt-image-2、gemini-3-pro-image-preview;视频当前只接通 Seedance 2.0 Fast(真实模型 doubao-seedance-2-0-fast-260128)。旧上游的 Nano Banana、Seedream、Kling、Veo 或浏览器本地自定义媒体模型不能进入生成下拉,避免同事选到实际不可用的模型。
2026-05-26 公司沉淀版:画布项目从浏览器本地存储升级为服务端 Postgres 持久化;localStorage 只作为离线缓存和首次导入来源。后端同时建立用户、任务、资源索引和审计表,保留原有 state.json 文件作为任务详情真源,避免一次迁移动到大文件资产结构。
+ 2026-05-26 AI 润色中性化:画布 AI 润色 不再复用 SKG 广告文案接口 /creative/copy。后端新增 POST /prompt/polish,前端 useChat、根画布输入框、文本节点和自动执行意图分析改走中性提示词/通用生成接口:只优化用户已经给出的主体、风格、镜头和细节,不主动添加 SKG、按摩产品、TikTok 广告话术或用户没有提到的品牌。
- 当前默认业务管线是“个人隔离任务 → 根域名进入个人画布 → 画布项目同步到服务端 Postgres → 用提示词、推荐词、AI 润色或工作流模板创建节点 → 画布自动执行或手动连接图片/视频/文本节点 → 生成结果沉淀在当前个人画布 → 需要时进入详情页继续编辑”。画布不再被削成三模式入口;首帧、尾帧、参考图、图生视频、多角度分镜、故事板和绘本等上游概念按节点能力保留。底层生成仍由 web/canvas-app/src/hooks/useApi.js 适配到本项目 /creative/jobs/image、/jobs/{id}/frames/{idx}/generate、/jobs/{id}/frames/{idx}/storyboard/video,并按当前登录用户写入个人 job。图片尺寸只显示 auto、1024x1536、1024x1024、1536x1024;视频画幅只显示 720x1280、1280x720、1024x1024、960x1280;视频时长只显示 5/8/10/12/15 秒。多人互不影响依赖后端 owner_id、画布项目 owner 和飞书 / 备用登录会话隔离。旧 React 单对话框首页、信息流复刻链路仍保留在源码里作为回滚/高级能力,但不作为生产默认入口。
+ 当前默认业务管线是“个人隔离任务 → 根域名进入个人画布 → 画布项目同步到服务端 Postgres → 用提示词、推荐词、AI 润色或工作流模板创建节点 → 画布自动执行或手动连接图片/视频/文本节点 → 生成结果沉淀在当前个人画布 → 需要时进入详情页继续编辑”。画布不再被削成三模式入口;首帧、尾帧、参考图、图生视频、多角度分镜、故事板和绘本等上游概念按节点能力保留。底层生成仍由 web/canvas-app/src/hooks/useApi.js 适配到本项目 /creative/jobs/image、/jobs/{id}/frames/{idx}/generate、/jobs/{id}/frames/{idx}/storyboard/video,AI 润色和通用 LLM 文本生成走 /prompt/polish 并保持中性专业,不再默认套入 SKG 广告语境。生成资产按当前登录用户写入个人 job。图片尺寸只显示 auto、1024x1536、1024x1024、1536x1024;视频画幅只显示 720x1280、1280x720、1024x1024、960x1280;视频时长只显示 5/8/10/12/15 秒。多人互不影响依赖后端 owner_id、画布项目 owner 和飞书 / 备用登录会话隔离。旧 React 单对话框首页、信息流复刻链路仍保留在源码里作为回滚/高级能力,但不作为生产默认入口。
01
个人任务
GET /jobs 按当前登录用户过滤;旧无 owner 任务只对备用账号可见。
02
进入画布
用户直接在根域名个人画布里操作;项目列表优先读取服务端 /canvas-projects,本地旧项目会首次导入。
@@ -611,7 +612,7 @@
web/canvas-app/src/stores/projects.js | 画布项目 Pinia store:启动时先读本地 localStorage["ai-canvas-projects"] 作为缓存,再调用 GET /canvas-projects 拉服务端项目;如果发现本地旧项目,会调用 POST /canvas-projects/import 导入到当前登录用户。新建、重命名、画布节点变更、复制和删除会同步到 /canvas-projects,本地缓存只用于快速打开和网络异常兜底。 |
web/canvas-app/src/views/Canvas.vue | 画布主交互:恢复上游底部 prompt composer、AI 润色、自动执行、推荐词、节点菜单、工作流面板、API/模型设置入口和批量下载入口。自动执行会调用 useWorkflowOrchestrator 分析提示词,创建文生图、图转视频、故事板、多角度分镜或绘本节点组;手动模式只创建文本节点,用户自行连接节点。 |
web/canvas-app/src/config/models.js | 画布媒体模型和规格的前端白名单:图片只内置 auto、gpt-image-2、gemini-3-pro-image-preview,尺寸只内置 auto、1024x1536、1024x1024、1536x1024;视频只内置 seedance / Seedance 2.0 Fast,画幅和时长对齐后端 /health 能力边界。useModelConfig.js 和 Pinia 模型 store 会忽略浏览器本地自定义图片/视频模型,防止旧缓存把不可用模型带回生成下拉。 |
-
web/canvas-app/src/hooks/useApi.js | 画布到本项目后端的适配层:不再读取浏览器 API Key,而是使用当前登录会话 Cookie 调用 /api。文生图 / 图生图先创建轻量 creative job,再调用 /frames/0/generate;文生视频 / 图生视频调用 /storyboard/video 并轮询 /jobs/{id},完成后把图片或 mp4 URL 写回画布节点。 |
+
web/canvas-app/src/hooks/useApi.js | 画布到本项目后端的适配层:不再读取浏览器 API Key,而是使用当前登录会话 Cookie 调用 /api。文生图 / 图生图先创建轻量 creative job,再调用 /frames/0/generate;文生视频 / 图生视频调用 /storyboard/video 并轮询 /jobs/{id},完成后把图片或 mp4 URL 写回画布节点。useChat 已从 SKG 广告文案接口切到 /prompt/polish:AI 润色显式使用 image/video prompt 模式,LLM 节点使用通用 chat 模式,避免自动注入用户没有提到的 SKG 或营销语境。 |
web/scripts/sync-canvas-root.mjs | 构建桥接脚本:在 next build 静态导出完成后,把 Vite 画布产物 web/canvas-app/dist 覆盖到 web/out 根目录,使 https://marketing.skg.com 登录后直接进入画布;旧 web/scripts/sync-canvas-dist.mjs 保留但不再由生产构建调用。 |
web/app/detail/page.tsx | 任务详情页:静态导出路由 /detail/?job=<id>,通过 query 读取 job id,调用 getJob 恢复同一任务。页面展示参考图、全部生成图、视频候选、营销图文方案和历史提示词,可继续调用 generateImage、generateStoryboardVideo、generateCreativeCopy,并支持删除图片/视频。该页继续依赖后端 owner 过滤,用户不能通过切换 URL 读取别人的任务。 |
web/app/agent/page.tsx | 新增一键出片终端页:只保留 TikTok 链接、产品图上传、实时 Agent Terminal 和最终成片播放器;通过 POST /agent-runs 创建受限后台状态机任务,通过 GET /agent-runs/{id} 轮询日志、进度、审片图和最终 mp4。该页不替代旧工作台深度编辑能力,只承接“用户只看成品”的快速出片主路径。 |
@@ -642,7 +643,7 @@
后端核心
- api/main.py | FastAPI 单文件后端:登录会话、状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、原音频转写/翻译、声音与背景音分析、后续口播改写/TTS、文件返回;同时承载全局 prompt_library 和 asset_library 的磁盘索引、CRUD、删除保护和复制到 job API。启动时会初始化 Postgres schema、扫描现有 state.json / 资源库并写入索引;新增 /canvas-projects 系列接口把画布项目按当前登录用户持久化。轻量创作入口 POST /creative/jobs/image 把上传图片或空白底图写成一个只有 0 号关键帧的 Job,让首页直接复用生图/生视频接口;该接口兼容无 body / JSON 空对象 / 正常 multipart 上传,避免无首帧文生图或文生视频时空 multipart 被 FastAPI 在业务前置解析阶段拒绝;/health 返回 database、image_options、image_size_options、video_options、video_size_options、video_duration_options 和 video_max_duration_seconds;/frames/{idx}/generate 的 model 字段用于图片模型偏好,size 字段用于图片输出尺寸;/storyboard/video 继续使用 model 字段选择视频别名,并先校验画幅与时长能力边界,然后把 GeneratedVideo 写成 queued 占位并进入进程内视频队列。队列默认 VIDEO_QUEUE_MAX_CONCURRENT=2、VIDEO_QUEUE_MAX_CONCURRENT_PER_USER=1,同一用户连续提交不会占满全局并发;排队任务会回写 queue_position、queue_size、queue_message。旧 AgentRun 一键出片状态机、TK 复刻接口和 POST /creative/copy 继续保留。 |
+ api/main.py | FastAPI 单文件后端:登录会话、状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、原音频转写/翻译、声音与背景音分析、后续口播改写/TTS、文件返回;同时承载全局 prompt_library 和 asset_library 的磁盘索引、CRUD、删除保护和复制到 job API。启动时会初始化 Postgres schema、扫描现有 state.json / 资源库并写入索引;新增 /canvas-projects 系列接口把画布项目按当前登录用户持久化。轻量创作入口 POST /creative/jobs/image 把上传图片或空白底图写成一个只有 0 号关键帧的 Job,让首页直接复用生图/生视频接口;该接口兼容无 body / JSON 空对象 / 正常 multipart 上传,避免无首帧文生图或文生视频时空 multipart 被 FastAPI 在业务前置解析阶段拒绝;POST /prompt/polish 用于中性 AI 润色和通用 LLM 文本生成,只保留用户明确给出的主体、品牌、产品、地点、风格和意图,不默认加入 SKG、按摩产品或短视频广告话术;/health 返回 database、image_options、image_size_options、video_options、video_size_options、video_duration_options 和 video_max_duration_seconds;/frames/{idx}/generate 的 model 字段用于图片模型偏好,size 字段用于图片输出尺寸;/storyboard/video 继续使用 model 字段选择视频别名,并先校验画幅与时长能力边界,然后把 GeneratedVideo 写成 queued 占位并进入进程内视频队列。队列默认 VIDEO_QUEUE_MAX_CONCURRENT=2、VIDEO_QUEUE_MAX_CONCURRENT_PER_USER=1,同一用户连续提交不会占满全局并发;排队任务会回写 queue_position、queue_size、queue_message。旧 AgentRun 一键出片状态机、TK 复刻接口和 POST /creative/copy 作为明确的 SKG 营销文案接口继续保留。 |
api/db.py | Postgres 适配层:在 DATABASE_URL 存在且 psycopg 可用时启用;负责建表、健康检查、用户 upsert、审计日志、画布项目 CRUD,以及把 Job、AgentRun、提示词库和素材库写入索引表。数据库不可用时本地开发会降级为 disabled,生产 verify-prod-docker.sh 会要求 database.connected=true。 |
video_model_options() | 视频模型能力出口:如果 seedance、kling、veo3、veo 等业务别名实际都映射到同一个真实模型,会按真实模型去重,只给前端返回一个可用选项;当前生产真实模型为 doubao-seedance-2-0-fast-260128,前端显示为 Seedance 2.0 Fast。后续只有在服务器真的配置了不同可用视频模型时,才应把新的模型重新暴露给画布。 |
api/product_library/skg-products | 内置 SKG 白底产品图库:manifest.json 记录从桌面产品图筛出的 gallery 白底图和桌面 4 张产品角度图,images/ 存 45 张参考图。 |
@@ -695,7 +696,7 @@ api/main.py
你看到的区域SKG 首页
-
主要源码web/app/page.tsx;前端 API client 在 web/lib/api.ts;轻量创作后端在 api/main.py 的 /creative/jobs/image、/creative/copy,实际图片和视频生成继续复用 /jobs/{id}/frames/{idx}/generate 与 /jobs/{id}/frames/{idx}/storyboard/video。
+
主要源码web/app/page.tsx;前端 API client 在 web/lib/api.ts;轻量创作后端在 api/main.py 的 /creative/jobs/image、/creative/copy、/prompt/polish,实际图片和视频生成继续复用 /jobs/{id}/frames/{idx}/generate 与 /jobs/{id}/frames/{idx}/storyboard/video。
适合怎么描述“首页只有一个对话框,三个模式是文生图、文生视频、图生视频;图生视频上传图片后手写提示词生成”。
@@ -1084,6 +1085,7 @@ ProductRefStateItem {
| 创建任务 | POST /jobs | createJob | 提交 TK 链接,后台开始下载;后端会把当前登录用户写入 Job.owner_*,后续详情、素材文件、删除和生成接口都通过统一中间件校验归属。下载阶段默认不带 cookies;生产环境必须显式保持 YTDLP_COOKIES_FILE= 和 YTDLP_COOKIES_FROM_BROWSER= 为空,避免容器内误读被打进镜像的开发 api/.env。 |
| 画布项目 | GET /canvas-projects
POST /canvas-projects
PUT /canvas-projects/{id}
GET /canvas-projects/{id}
DELETE /canvas-projects/{id}
POST /canvas-projects/import | web/canvas-app/src/stores/projects.js | 根域名画布项目的服务端持久化接口。列表和详情按当前登录用户过滤;写入时保存画布 JSON、缩略图、可见性、版本和更新时间;删除为软删除。首次上线后本地 localStorage 旧项目会通过 import 导入到当前用户,之后服务端 Postgres 是主存储。 |
| 画布生成 | POST /creative/jobs/image
POST /jobs/{id}/frames/upload
POST /jobs/{id}/frames/{idx}/generate
POST /jobs/{id}/frames/{idx}/storyboard/video
GET /jobs/{id} | web/canvas-app/src/hooks/useApi.js | 画布项目结构保存在 /canvas-projects;一旦生成图片或视频,就通过同一套 creative job / frame / storyboard video 接口写入当前登录用户自己的 job 目录。文生图会创建空白 creative job 后生成图片;图生视频会把上传图转成 frame 并作为视频参考图提交,提交视频后用 skg:{jobId}:{videoId} 作为画布侧任务 id 轮询 /jobs/{id},直到视频状态完成或失败。 |
+
| AI 润色 / LLM 节点 | POST /prompt/polish | web/canvas-app/src/hooks/useApi.js
web/canvas-app/src/api/chat.js | 中性的提示词润色和通用文本生成接口。根画布和文本节点传 mode=image、默认输出英文提示词;LLM 节点和自动执行意图分析传 mode=chat、保持输入语言。接口会遵守 system prompt,但明确禁止自动添加用户没有提到的 SKG、按摩产品、短视频广告 framing、营销标题或 hashtag。 |
| 一键出片终端 | POST /agent-runs
GET /agent-runs
GET /agent-runs/{id}
GET /agent-runs/{id}/final.mp4
GET /agent-runs/{id}/contact.jpg | web/app/agent/page.tsx | 快速出片页的唯一主接口。前端提交 TikTok 链接和最多 6 张产品图;后端创建同 owner 的 Job 与 AgentRun,后台执行下载、产品图归一化、透明骨架主体参考复制、12 段镜头计划、视频生成、失败镜头自动重跑一次、审片接触表和 ffmpeg 最终合成。列表、详情、最终 mp4 和接触表同样按 owner 隔离。 |
| 重试下载 | POST /jobs/{id}/download/retry | retryJobDownload | 用于 TK 链接下载失败且没有 video_url 的素材;清空错误、重新进入下载状态,并在后台再次执行 pipeline_download。上传视频不能重下载,需要重新上传文件。 |
| 上传视频 | POST /jobs/upload | uploadJob | 保存 source.mp4,然后同样进入下载完成状态;当前上传后也加入第一步队列,下载完成后自动解析音频。 |
@@ -1241,6 +1243,18 @@ ProductRefStateItem {
变更记录
这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。
+
+
+ 2026-05-26 · AI 润色从 SKG 广告文案拆出
+ API
+ Canvas
+
+
+
问题:画布 AI 润色 之前复用 /creative/copy,该接口本来是 SKG 营销短视频文案生成器,会默认加入 SKG、健康科技、按摩产品、TikTok/Reels 广告语境,导致普通图片或视频提示词也被带偏。
+
改动:api/main.py 新增中性 POST /prompt/polish;web/canvas-app/src/hooks/useApi.js 改为调用该接口并传入 system_prompt、mode 和 target_language。根画布和文本节点显式用 mode=image 输出英文生成提示词;LLM 节点和自动执行意图分析用 mode=chat 保持输入语言。
+
影响:AI 润色只优化用户原本写的主体、风格、镜头、光线、构图和细节,不再主动添加用户没提到的品牌、产品或营销话术;/creative/copy 继续保留给明确的 SKG 营销文案生成场景。
+
+
2026-05-26 · 视频生成失败改为员工可读提示
diff --git a/web/canvas-app/src/api/chat.js b/web/canvas-app/src/api/chat.js
index 36e96dc..da9541e 100644
--- a/web/canvas-app/src/api/chat.js
+++ b/web/canvas-app/src/api/chat.js
@@ -15,12 +15,18 @@ export const chatCompletions = (data) =>
// 流式对话补全
export const streamChatCompletions = async function* (data, signal, options = {}) {
const text = data?.messages?.at?.(-1)?.content || data?.goal || ''
- const response = await fetch('/api/creative/copy', {
+ const systemPrompt = data?.messages?.find?.((message) => message?.role === 'system')?.content || ''
+ const response = await fetch('/api/prompt/polish', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
- body: JSON.stringify({ goal: typeof text === 'string' ? text : JSON.stringify(text), seconds: 15 }),
+ body: JSON.stringify({
+ text: typeof text === 'string' ? text : JSON.stringify(text),
+ system_prompt: systemPrompt,
+ mode: 'chat',
+ target_language: 'keep'
+ }),
signal
})
@@ -30,6 +36,5 @@ export const streamChatCompletions = async function* (data, signal, options = {}
}
const json = await response.json()
- const variant = json.variants?.[0]
- yield variant?.image_prompt_en || variant?.video_prompt_en || ''
+ yield json.text || ''
}
diff --git a/web/canvas-app/src/components/nodes/LLMConfigNode.vue b/web/canvas-app/src/components/nodes/LLMConfigNode.vue
index d31aa23..10dc964 100644
--- a/web/canvas-app/src/components/nodes/LLMConfigNode.vue
+++ b/web/canvas-app/src/components/nodes/LLMConfigNode.vue
@@ -695,7 +695,9 @@ const formatOptions = [
const chatHook = computed(() => {
return useChat({
systemPrompt: systemPrompt.value,
- model: model.value
+ model: model.value,
+ mode: 'chat',
+ targetLanguage: 'keep'
})
})
@@ -838,7 +840,9 @@ const handleGenerate = async () => {
const { send } = useChat({
systemPrompt: resolvedSystemPrompt,
- model: model.value
+ model: model.value,
+ mode: 'chat',
+ targetLanguage: 'keep'
})
// 如果 user 消息为空,使用简单提示
diff --git a/web/canvas-app/src/components/nodes/TextNode.vue b/web/canvas-app/src/components/nodes/TextNode.vue
index da4d97c..755a2e2 100644
--- a/web/canvas-app/src/components/nodes/TextNode.vue
+++ b/web/canvas-app/src/components/nodes/TextNode.vue
@@ -116,8 +116,10 @@ const isApiConfigured = computed(() => !!modelStore.currentApiKey)
// Chat hook for polish | 润色用的 Chat hook
const { send: sendChat } = useChat({
- systemPrompt: '你是一个专业的AI绘画提示词专家。将用户输入的内容美化成高质量的生图提示词,包含风格、光线、構图、细节等要素。直接返回提示词,不要其他解释。',
- model: 'gpt-4o-mini'
+ systemPrompt: '你是一个专业的 AI 绘画提示词编辑。只优化用户已经给出的主体、风格、光线、构图和细节,不添加用户没有提到的品牌、产品或营销话术。直接返回提示词,不要其他解释。',
+ model: 'gpt-4o-mini',
+ mode: 'image',
+ targetLanguage: 'en'
})
// Local content state | 本地内容状态
diff --git a/web/canvas-app/src/hooks/useApi.js b/web/canvas-app/src/hooks/useApi.js
index bc1a70d..52c3942 100644
--- a/web/canvas-app/src/hooks/useApi.js
+++ b/web/canvas-app/src/hooks/useApi.js
@@ -127,7 +127,7 @@ export const useApiState = () => {
return { loading, error, status, reset, setLoading, setError, setSuccess }
}
-export const useChat = () => {
+export const useChat = (options = {}) => {
const { loading, error, status, reset, setLoading, setError, setSuccess } = useApiState()
const messages = ref([])
const currentResponse = ref('')
@@ -137,12 +137,17 @@ export const useChat = () => {
setLoading(true)
stopped = false
try {
- const response = await requestJson('/creative/copy', {
+ const mode = options.mode || 'chat'
+ const response = await requestJson('/prompt/polish', {
method: 'POST',
- body: JSON.stringify({ goal: content, seconds: 15 })
+ body: JSON.stringify({
+ text: content,
+ system_prompt: options.systemPrompt || '',
+ mode,
+ target_language: options.targetLanguage || (mode === 'chat' ? 'keep' : 'en')
+ })
})
- const variant = response.variants?.[0]
- const result = variant?.image_prompt_en || variant?.video_prompt_en || content
+ const result = response.text || content
if (!stopped) {
currentResponse.value = result
messages.value.push({ role: 'user', content })
diff --git a/web/canvas-app/src/views/Canvas.vue b/web/canvas-app/src/views/Canvas.vue
index 05db26d..cdd35a2 100644
--- a/web/canvas-app/src/views/Canvas.vue
+++ b/web/canvas-app/src/views/Canvas.vue
@@ -299,12 +299,12 @@ onMounted(() => {
const CHAT_TEMPLATES = {
imagePrompt: {
name: '生图提示词',
- systemPrompt: '你是一个专业的AI绘画提示词专家。将用户输入的内容美化成高质量的生图提示词,包含风格、光线、構图、细节等要素。直接返回提示词,不要其他解释。',
+ systemPrompt: '你是一个专业的 AI 绘画提示词编辑。只优化用户已经给出的主体、风格、光线、构图和细节,不添加用户没有提到的品牌、产品或营销话术。直接返回提示词,不要其他解释。',
model: 'gpt-4o-mini'
},
videoPrompt: {
name: '视频提示词',
- systemPrompt: '你是一个专业的AI视频提示词专家。将用户输入的内容美化成高质量的视频生成提示词,包含运动、场景、镜头等要素。直接返回提示词,不要其他解释。',
+ systemPrompt: '你是一个专业的 AI 视频提示词编辑。只优化用户已经给出的主体、动作、场景、镜头和节奏,不添加用户没有提到的品牌、产品或营销话术。直接返回提示词,不要其他解释。',
model: 'gpt-4o-mini'
}
}
@@ -320,7 +320,9 @@ const {
send: sendChat
} = useChat({
systemPrompt: CHAT_TEMPLATES.imagePrompt.systemPrompt,
- model: CHAT_TEMPLATES.imagePrompt.model
+ model: CHAT_TEMPLATES.imagePrompt.model,
+ mode: 'image',
+ targetLanguage: 'en'
})
// Workflow orchestrator hook | 工作流编排 hook