From a24dbb868a5695662eea5d9b38449646587f5c3c Mon Sep 17 00:00:00 2001 From: seaislee1209 Date: Tue, 23 Jun 2026 00:47:01 +0800 Subject: [PATCH] =?UTF-8?q?refactor(extract):=20=E5=86=99=E6=AD=BB?= =?UTF-8?q?=E5=A5=91=E7=BA=A6=E7=98=A6=E8=BA=AB=E4=B8=BA=E7=BA=AF=E7=BB=93?= =?UTF-8?q?=E6=9E=84,craft=20=E5=85=A8=E4=BA=A4=E7=BB=99=20skill(=E6=B6=88?= =?UTF-8?q?=E9=99=A4=E9=87=8D=E5=A4=8D/=E6=BC=82=E7=A7=BB=E3=80=81?= =?UTF-8?q?=E4=B8=8D=E9=99=8D=E8=B4=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 承上轮讨论(商业级质量考量):写死的 _EXTRACT_OUTPUT_CONTRACT 原先掺了 craft 规则 (穿搭/空手/字数/visual_prompt 写法),与 skill 正文重复 → 有漂移、稀释质量之虞。 现只留「格式骨架」(JSON 形状 / character|scene 两类 / 不提商品 / id 规则 / segments 覆盖每镜 / 只输出 JSON);所有创作细则一律以 skill 正文为准。定位不变:skill 丢了也 保证出 JSON 不塌(流水线硬底线),质量则 100% 由 skill 单点驱动。 验证(全在瘦身版上): - 完整 Django 套件 152/152 全绿。 - 真调豆包「瘦身前 vs 瘦身后」对比:角色/场景/segments 一致,visual_prompt 仍守住 空手/不提商品/空镜/字数(craft 由 skill 驱动)—— 质量零退步。 - 本地起后端(sqlite+eager+真ARK)+前端+无头 chromium 真点提取按钮:闸门→提取→ 角色(女主/室友)场景(学生宿舍/大学教室)落库、entities_extracted=True、 任务 succeeded、system_chars=7482(非空)、0 控制台错误。 可回退:tag extract-ok-baseline(66778fa)。 Co-Authored-By: Claude Opus 4.8 (1M context) --- core/backend/apps/ai/services.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/backend/apps/ai/services.py b/core/backend/apps/ai/services.py index 062a9e2..28e7624 100644 --- a/core/backend/apps/ai/services.py +++ b/core/backend/apps/ai/services.py @@ -375,24 +375,24 @@ _EXTRACT_INFLIGHT = ( # 写死的提取输出契约兜底(对齐脚本 agent 的 _OUTPUT_PROTOCOL):随代码进镜像、永远在。 -# 即便 skill 文件丢失/为空,模型也仍收到「只输出这套 JSON」的硬指令 → 不会再退化成吐散文 → 解析失败。 -# 这是历史事故(skills 没打进镜像 → 提取 system 全空 → 解析失败)的根治性兜底,与 skill 正文不冲突(互相强化)。 +# **只管"格式骨架"**(JSON 形状 / id 规则 / 不提商品 / 只输出 JSON)—— 这是流水线硬底线,skill 丢了也不会塌。 +# **不碰任何"创作细则"**(穿搭/空手/字数/visual_prompt 怎么写),那些归 skill 正文独占,避免两处重复→漂移→稀释质量。 _EXTRACT_OUTPUT_CONTRACT = """ --- -## 输出契约(硬性 · 优先级最高) -你是电商短视频「实体提取」agent。读【商品信息】+【分镜脚本】,认出**角色(出镜的人)**和**场景(地点/环境)**, -**只输出且仅输出一个 JSON 对象**(UTF-8,无注释,不要 ```json 代码块外的任何散文/解释/markdown): +## 输出契约(硬性 · 仅格式底线) +**只输出且仅输出一个 JSON 对象**(UTF-8,无注释,无 ```json 代码块外的任何散文/解释/markdown),形状如下: { "entities": [ - {"id": "c1", "type": "character", "name": "女主", "visual_prompt": "一句生图描述(20-45字,只写人物本身:年龄/外形/气质/整套穿搭;空手、不带与商品同类的物件)"}, - {"id": "s1", "type": "scene", "name": "地点名", "visual_prompt": "一句空镜环境描述(20-40字,不写人)"} + {"id": "c1", "type": "character", "name": "角色称呼", "visual_prompt": "一句生图描述"}, + {"id": "s1", "type": "scene", "name": "地点名", "visual_prompt": "一句生图描述"} ], "segments": [{"index": 0, "entity_refs": ["c1", "s1"]}] } -硬性规则:① **绝不输出商品/product 实体**(商品由系统用真实主图注入);② 角色 id 用 c1/c2…、场景 id 用 s1/s2…,各最多 6 个、严格去重; -③ segments 必须覆盖输入每一镜,index 从 0 开始,每镜列出该镜出现的角色/场景的 id;④ 整个回复就是那个 JSON,不要任何前后缀。 +硬性规则(**仅格式;角色/场景怎么写、穿搭/visual_prompt 细则一律以上文技能正文为准**): +① 只认 character / scene 两类,**绝不输出 product 商品实体**;② 角色 id 用 c1/c2…、场景 id 用 s1/s2…,严格去重; +③ segments 必须覆盖输入每一镜(index 从 0 开始),列出该镜出现的角色/场景 id;④ 整个回复就是那个 JSON,无前后缀。 """