From c415cd0aba538fba46be39289f59d69953f2212b Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 26 May 2026 10:00:47 +0800 Subject: [PATCH] auto-save 2026-05-26 10:00 (~2) --- .memory/worklog.json | 77 ++++++++++++++++++++------------------- api/main.py | 87 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 38 deletions(-) diff --git a/.memory/worklog.json b/.memory/worklog.json index 82ff4ce..fe1550e 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,43 +1,5 @@ { "entries": [ - { - "files_changed": 3, - "hash": "d6bba9d", - "message": "auto-save 2026-05-20 14:45 (~3)", - "ts": "2026-05-20T14:45:09+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-20 14:45 (~3)", - "ts": "2026-05-20T06:53:59Z", - "type": "session-heartbeat" - }, - { - "files_changed": 2, - "message": "启动 Claude 接力会话 · 已载入 Claude / Codex 最近会话,等待下一条指令 · 分支 main · 2 项未提交变更 · 最近提交:auto-save 2026-05-20 14:45 (~3)", - "ts": "2026-05-20T06:57:19Z", - "type": "assistant-session" - }, - { - "files_changed": 2, - "hash": "1e995c3", - "message": "auto-save 2026-05-20 15:01 (~2)", - "ts": "2026-05-20T15:01:24+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-20 15:01 (~2)", - "ts": "2026-05-20T07:03:59Z", - "type": "session-heartbeat" - }, - { - "files_changed": 1, - "message": "Claude 会话活跃 · 最近命令:claude · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-20 15:01 (~2)", - "ts": "2026-05-20T07:07:21Z", - "type": "session-heartbeat" - }, { "files_changed": 2, "message": "Claude 会话结束 · 持续 0 秒 · 最近命令:claude · 分支 main · 2 项未提交变更 · 最近提交:auto-save 2026-05-20 15:01 (~2)", @@ -3206,6 +3168,45 @@ "type": "session-heartbeat", "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:chore: migrate legacy password data to Feishu owner", "files_changed": 1 + }, + { + "ts": "2026-05-26T09:39:00+08:00", + "type": "commit", + "message": "auto-save 2026-05-26 09:38 (~2)", + "hash": "836a33e", + "files_changed": 2 + }, + { + "ts": "2026-05-26T01:39:34Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 2 项未提交变更 · 最近提交:auto-save 2026-05-26 09:38 (~2)", + "files_changed": 2 + }, + { + "ts": "2026-05-26T09:41:03+08:00", + "type": "commit", + "message": "fix: explain video generation failures", + "hash": "579e538", + "files_changed": 2 + }, + { + "ts": "2026-05-26T09:43:02+08:00", + "type": "commit", + "message": "docs: record video error deployment", + "hash": "591bc37", + "files_changed": 1 + }, + { + "ts": "2026-05-26T01:49:34Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:docs: record video error deployment", + "files_changed": 1 + }, + { + "ts": "2026-05-26T01:59:34Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 2 项未提交变更 · 最近提交:docs: record video error deployment", + "files_changed": 2 } ] } diff --git a/api/main.py b/api/main.py index db1c011..a666c28 100644 --- a/api/main.py +++ b/api/main.py @@ -5268,6 +5268,18 @@ class CreativeCopyResp(BaseModel): variants: list[CreativeCopyVariant] +class PromptPolishReq(BaseModel): + text: str + system_prompt: str = "" + mode: Literal["image", "video", "general"] = "image" + target_language: Literal["en", "zh", "keep"] = "en" + + +class PromptPolishResp(BaseModel): + model: str + text: str + + class ScriptRewriteSegmentReq(BaseModel): index: int start: float = 0.0 @@ -5400,6 +5412,81 @@ def _parse_creative_copy_response(raw: str, req: CreativeCopyReq) -> CreativeCop return CreativeCopyResp(model=REWRITE_MODEL if LLM_API_KEY else "fallback", variants=variants) +def _prompt_polish_fallback(req: PromptPolishReq) -> PromptPolishResp: + text = req.text.strip() + base = _ensure_english(text) if req.target_language == "en" else text + base = re.sub(r"\s+", " ", base).strip() + if req.mode == "video": + polished = ( + f"{base}. Smooth camera movement, clear subject continuity, stable composition, " + "natural motion, coherent lighting, no subtitles, no watermark." + ) + elif req.mode == "general": + polished = base + else: + polished = ( + f"{base}. Detailed visual prompt, clear main subject, coherent composition, " + "natural lighting, refined color palette, high-quality details." + ) + return PromptPolishResp(model="fallback", text=polished[:1800]) + + +@app.post("/prompt/polish", response_model=PromptPolishResp) +def polish_prompt(req: PromptPolishReq) -> PromptPolishResp: + text = req.text.strip() + if not text: + raise HTTPException(400, "text required") + if not LLM_API_KEY: + return _prompt_polish_fallback(req) + + target_label = { + "en": "English", + "zh": "Simplified Chinese", + "keep": "the same language as the input", + }.get(req.target_language, "English") + mode_hint = { + "image": "an image-generation prompt", + "video": "a video-generation prompt", + "general": "a concise generation prompt", + }.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 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 == "video": + prompt += ( + "For video, describe motion, timing, camera movement, continuity, and what changes over time. " + "If people are not essential, prefer no recognizable faces or distant/turned-away background people to reduce video safety risk.\n" + ) + if user_system: + prompt += f"\nUser-selected polishing guidance:\n{user_system[:1000]}\n" + prompt += f"\nInput:\n{text[:2500]}" + + try: + resp = llm().chat.completions.create( + model=REWRITE_MODEL, + messages=[ + {"role": "system", "content": "You are a neutral professional prompt editor. You preserve intent and never inject unrelated brands or products."}, + {"role": "user", "content": prompt}, + ], + temperature=0.45, + max_tokens=900, + ) + out = (resp.choices[0].message.content or "").strip() + out = re.sub(r"^```(?:text)?\s*", "", out, flags=re.I).strip() + out = re.sub(r"\s*```$", "", out).strip() + out = re.sub(r'^[\'"「『]+|[\'"」』]+$', "", out).strip() + return PromptPolishResp(model=REWRITE_MODEL, text=(out or _prompt_polish_fallback(req).text)[:1800]) + except Exception as e: + print(f"[prompt polish fallback] {e}", flush=True) + return _prompt_polish_fallback(req) + + @app.post("/translate") def translate_text(req: TranslateReq) -> dict: """单条文本翻译(给生图自定义提取元素 zh→en 用)"""