feat: deepseek 的一些修改

This commit is contained in:
Joey
2026-08-16 22:20:15 +08:00
parent b57933e983
commit 9d15d8f784
14 changed files with 229 additions and 35 deletions
+14 -4
View File
@@ -296,6 +296,7 @@ async def run_suite(suite_id: str) -> None:
]
ok, failed = 0, 0
failures: list[str] = []
for job in jobs:
type_id = job["kind"]
image_row = SuiteImage(
@@ -309,7 +310,7 @@ async def run_suite(suite_id: str) -> None:
try:
prompt = build_prompt(
type_id, ctx, suite.style_set, suite.lang,
extra=job, style_prompt=suite.style_prompt,
extra=job, style_prompt=suite.style_prompt, requirements=suite.requirements,
)
if product:
refs = await _select_ref_images(db, product.id, type_id)
@@ -322,13 +323,22 @@ async def run_suite(suite_id: str) -> None:
ok += 1
except Exception as exc: # noqa: BLE001
log.exception("套图 %s 类型 %s 生成失败", suite_id, type_id)
image_row.error = str(exc)[:500]
err = str(exc)[:500]
image_row.error = err
failures.append(f"{job.get('title') or type_name(type_id)}{err[:200]}")
failed += 1
await db.commit()
suite.status = SUITE_DONE if failed == 0 else (SUITE_PARTIAL if ok > 0 else SUITE_FAILED)
if failed and not ok:
suite.error = "全部生成失败,请检查 API Key / 参考图"
if failed:
uniq = list(dict.fromkeys(failures)) # 去重保序
detail = "".join(uniq[:6])
if len(uniq) > 6:
detail += f";…等共 {failed} 张失败"
if ok == 0:
suite.error = f"全部生成失败。{detail}"
else:
suite.error = f"部分生成失败({failed} 张)。{detail}"
from datetime import datetime, timezone
suite.finished_at = datetime.now(timezone.utc)
if product:
+37 -4
View File
@@ -44,6 +44,31 @@ SYSTEM_PROMPT = """你是一名资深电商视觉策划。根据商品信息规
{"summary":"三色收纳盒全套图","items":[{"kind":"white_bg","title":"主图·粉色","detail":"粉色SKU白底主视觉","prompt_hint":"front view on white background","count":1,"variant_name":"粉色"}]}"""
def _system_prompt_with_requirements(requirements: str | None) -> str:
"""把生图要求作为最高优先级约束注入 system prompt(置于规划规则之前)。
不仅声明优先级,还明确要求把要求落地到每个方案项的 prompt_hint
避免模型只把要求当作背景信息而不影响输出。
"""
if not (requirements and requirements.strip()):
return SYSTEM_PROMPT
marker = "\n## 输出硬性约束"
idx = SYSTEM_PROMPT.find(marker)
if idx < 0:
return SYSTEM_PROMPT
req = requirements.strip()
block = (
"\n## 生图要求(最高优先级,硬性约束,覆盖下方所有规划规则与约束)\n"
+ req
+ "\n\n"
+ "规划方案时,必须把上述生图要求落地到每一项:\n"
+ "1. 每个方案项的 prompt_hint 必须融入上述要求的关键约束(如要求纯黑背景,则每个 prompt_hint 都要写明 black background);\n"
+ "2. title / detail 措辞不得与上述要求矛盾;\n"
+ "3. 任何规划规则与上述要求冲突时,一律以本生图要求为准。\n"
)
return SYSTEM_PROMPT[:idx] + block + SYSTEM_PROMPT[idx:]
def _normalize_items(raw_items: list, sku_variants: list[str]) -> list[dict]:
"""清洗模型输出:kind 白名单、count 钳制、variant 必须真实存在。"""
items: list[dict] = []
@@ -127,18 +152,26 @@ async def generate_plan(
sku_variants: list[str],
image_stats: dict,
platform: str,
requirements: str | None = None,
) -> dict:
"""调用 DeepSeek 生成方案。返回 {summary, items}。"""
"""调用 DeepSeek 生成方案。返回 {summary, items}。
requirements:生图要求,最高优先级注入 system prompt,规划方案必须遵循。
"""
s = get_settings()
if not s.deepseek_api_key:
raise RuntimeError("未配置 DEEPSEEK_API_KEY.env")
user_content = json.dumps({
user_payload: dict = {
"商品信息": product_info, # {title, desc, params:[{key,value}], sellingPoints, price}
"SKU规格": sku_variants, # 带图的 SKU 规格名(variant_name 只能从中选)
"图片统计": image_stats, # {main: n, sku: n, detail: n}
"目标平台": platform, # ozon/wb/cn(决定图内文案语言)
}, ensure_ascii=False)
}
# 生图要求同时在 user 侧强调(与 system prompt 双重约束),确保模型真正遵循
if requirements and requirements.strip():
user_payload["生图要求(最高优先级,必须体现在每个方案项中)"] = requirements.strip()
user_content = json.dumps(user_payload, ensure_ascii=False)
async with httpx.AsyncClient(timeout=90, verify=False) as client:
resp = await client.post(
@@ -147,7 +180,7 @@ async def generate_plan(
json={
"model": s.deepseek_model,
"messages": [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "system", "content": _system_prompt_with_requirements(requirements)},
{"role": "user", "content": user_content},
],
"response_format": {"type": "json_object"},
+12 -1
View File
@@ -283,12 +283,14 @@ _PROMPT_BUILDERS = {
def build_prompt(type_id: str, ctx: dict, style_set: int, lang: str, extra: dict | None = None,
style_prompt: str | None = None) -> str:
style_prompt: str | None = None, requirements: str | None = None) -> str:
"""构造指定图类型的完整生图 prompt。
extra: 方案项信息 {title, detail, prompt_hint}——custom 类型必需,
预设类型也会把 prompt_hint 作为构图补充注入。
style_prompt: 用户改写的风格提示词,覆盖 style_set 内置模板(tone/bg 整体替换)。
requirements: 生图要求(最高优先级,强制约束),置于 prompt 最前面,
声明覆盖一切冲突指令,用户可在此输入强制要求。
"""
if style_prompt and style_prompt.strip():
style = {"name": "custom", "tone": style_prompt.strip(), "bg": ""}
@@ -305,6 +307,15 @@ def build_prompt(type_id: str, ctx: dict, style_set: int, lang: str, extra: dict
hint = (extra.get("prompt_hint") or "").strip()
if hint:
prompt = prompt.rstrip(".") + f". Additional composition guidance: {hint}."
# 生图要求:最高优先级,置于最前并声明覆盖冲突指令(用户输入原样保留,不翻译)
if requirements and requirements.strip():
prompt = (
"STRICT REQUIREMENTS (highest priority, must be followed exactly, "
"override any conflicting instruction): "
+ requirements.strip().rstrip(".")
+ ". "
+ prompt
)
return prompt + ". " + DEFAULT_NEGATIVE_INTENT