test-plan-fixture.mjs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { compileProductLock } from "../mcp/src/providers/commerce-vision-provider.mjs";
  2. function repeatToLength(seed, minimum) {
  3. let result = seed;
  4. while ([...result].length < minimum) result += ` ${seed}`;
  5. return result;
  6. }
  7. const identityManifest = {
  8. must_preserve: ["完整外形轮廓", "商品数量", "主体颜色", "可见结构", "标识位置"],
  9. must_not_add: ["额外配件", "额外文字", "不存在的纽扣"],
  10. unknown_do_not_assert: ["内部结构", "真实尺寸", "材质成分"],
  11. };
  12. identityManifest.product_lock = compileProductLock(identityManifest);
  13. const slotConfigs = [
  14. ["hero", "isolated_product", "simple", "看清完整商品外观与数量", ["visible_fact:1"], "", "纯净无缝背景中只放置一个完整商品,保留充分边距、自然接触阴影与清楚轮廓。"],
  15. ["selling_point", "material_demonstration", "medium", "理解第一项可见材质价值", ["visible-sp-1"], "visible-sp-1", "以单一方向的掠射光划过商品表面,并用明暗渐变和局部微观纹理展示第一项可见材质特征;画面仍保留足够完整外形作为识别锚点,不加入说明文字或虚构性能。"],
  16. ["scene", "environmental_scene", "complex", "理解商品与完整生活空间的关系", ["suggested_scene:1"], "", "建立具有前景家具、中景商品与远景建筑层次的宽幅生活空间。商品自然位于真实承托面上,附近道具只用于交代尺度与情境,左右留出呼吸空间;环境细节、材质反射与光影方向互相呼应,不宣称未经证实的适用性。"],
  17. ["selling_point", "feature_demonstration", "medium", "理解第二项可见结构价值", ["visible-sp-2"], "visible-sp-2", "用侧向中近景展示与第二项卖点相关的可见结构,并让完整商品处于同一连续空间的后景作为关系参照;通过景深和连续空间层次区分重点,禁止虚构内部构造、功能或性能。"],
  18. ["decision_support", "multi_angle", "medium", "从多个真实可见角度完成外观判断", ["visible_fact:2"], "", "在唯一一张多格构图中,以等比例、等光色的三个外观视角建立横向阅读顺序;所有视角都只展示参考图支持的外部表面,间距清楚,不生成未知背面、内部、附件或说明文字。"],
  19. ["scene", "human_interaction", "complex", "理解人物动作与商品之间的关系", ["suggested_audience:1"], "", "人物从画面侧边进入,以明确、自然且符合商品可见结构的手部动作与商品发生联系。前景动作、中景商品和背景环境形成三层空间,服装、道具与光线克制统一;商品仍是视觉焦点,不遮挡身份特征,不添加未证实用途。"],
  20. ["decision_support", "usage_sequence", "medium", "理解商品在单一使用时刻中的状态关系", ["visible_fact:3"], "", "在一个连续、真实的桌面或生活空间中呈现商品与必要使用动作的前后关系,以视线方向、手部位置和物体间距传达顺序,保持单一连续画面,不加入步骤文字、测量值、营销结论或未知附件。"],
  21. ].map(([category, render, complexity, decision, evidence, sellingPointId, scene]) => ({
  22. category, render, complexity, decision, evidence, sellingPointId, scene,
  23. }));
  24. function buildModules(index, config) {
  25. const sceneMinimum = config.complexity === "complex" ? 175 : config.complexity === "medium" ? 75 : 25;
  26. return {
  27. product_lock: identityManifest.product_lock,
  28. image_job: `第${index + 1}张图只承担一个决策任务:${config.decision}。`,
  29. scene: repeatToLength(config.scene, sceneMinimum),
  30. composition: `第${index + 1}张使用独立的裁切、占比、边距、空间深度与阅读顺序,不能复用其他槽位的机位关系。`,
  31. lighting_material: `第${index + 1}张使用独立光线方向、光源面积、软硬度、色温、阴影和真实材质响应。`,
  32. camera_style: config.complexity === "complex"
  33. ? `为第${index + 1}张指定独立镜头焦段、焦平面和景深过渡。`
  34. : `第${index + 1}张采用独立的商业摄影机位与成像方式。`,
  35. text_layout: "",
  36. negative_constraints: `禁止商品漂移、无关物体、重复商品、虚构卖点、水印和额外品牌;禁止断言内部结构、真实尺寸或材质成分。`,
  37. };
  38. }
  39. export function compilePrompt(modules) {
  40. return Object.values(modules).filter(Boolean).join(" ");
  41. }
  42. export function buildValidPlan(
  43. category = "generic consumer product",
  44. reference = "https://images.example.test/product.jpg",
  45. runId = `cross-category-${category.replace(/\s+/g, "-")}`,
  46. ) {
  47. return {
  48. schema_version: "0.6",
  49. run_id: runId,
  50. status: "ready",
  51. user_output_mode: "images_only",
  52. request: {
  53. instruction: "这是我的产品,帮我生成一套通用电商七图。",
  54. reference_images: [reference],
  55. },
  56. context: {
  57. platform: "general_ecommerce",
  58. market: "unspecified",
  59. voc: { status: "unavailable", findings: [] },
  60. },
  61. product_understanding: {
  62. category,
  63. product_name: { value: category, basis: "verified visible evidence", confidence: "medium" },
  64. visible_facts: ["完整外形可见", "正面与侧面轮廓可见", "可见操作结构", "主色和表面材质观感可见"],
  65. verified_visible_facts: ["完整外形可见", "正面与侧面轮廓可见", "可见操作结构", "主色和表面材质观感可见"],
  66. inferred_attributes: [],
  67. unknown_features: ["内部结构", "真实尺寸", "材质成分"],
  68. identity_manifest: identityManifest,
  69. provided_facts: [],
  70. candidate_selling_points: [
  71. { id: "visible-sp-1", value: "可见材质与主色形成清晰的视觉识别", basis_refs: ["visible_fact:4"], confidence: "high" },
  72. { id: "visible-sp-2", value: "可见结构关系让商品外观层次容易理解", basis_refs: ["visible_fact:2", "visible_fact:3"], confidence: "high" },
  73. ],
  74. visible_specs: { visible_quantity: "1", exterior_state: "complete" },
  75. creative_positioning: ["克制、清晰的商业视觉"],
  76. suggested_audiences: ["重视清晰商品信息的消费者"],
  77. suggested_scenes: ["整洁、可信的日常使用环境"],
  78. unsupported_claims: ["经过认证", "超长耐用"],
  79. unknowns: ["内部结构", "真实尺寸", "材质成分"],
  80. },
  81. global_consistency_lock: {
  82. product_invariants: identityManifest.must_preserve,
  83. visual_system: ["统一商品身份与真实材质响应"],
  84. prohibited_changes: identityManifest.must_not_add,
  85. },
  86. set_blueprint: {
  87. business_allocation: { hero: 1, scene: 2, selling_point: 2, decision_support: 2 },
  88. visual_thesis: "用七个不可互换的购买任务让商品可识别、可理解、可代入并可判断。",
  89. narrative_arc: ["识别", "理解价值", "代入", "决策"],
  90. shared_visual_dna: ["商品身份", "核心色彩", "真实材质"],
  91. intentional_variations: ["业务任务", "空间", "人物", "景别", "信息关系"],
  92. },
  93. images: slotConfigs.map((config, index) => {
  94. const modules = buildModules(index, config);
  95. return {
  96. id: String(index + 1).padStart(2, "0"),
  97. role: config.category,
  98. business_category: config.category,
  99. decision_subject: config.decision,
  100. evidence_refs: config.evidence,
  101. selling_point_id: config.sellingPointId,
  102. purpose: config.decision,
  103. voc_refs: [],
  104. set_design: {
  105. render_family: config.render,
  106. scene_complexity: config.complexity,
  107. unique_visual_hook: `槽位${index + 1}使用${config.render}形成不可互换的视觉任务。`,
  108. contrast_with_previous: index === 0 ? "开场" : `槽位${index + 1}改变景别、空间、动作和信息关系。`,
  109. },
  110. shot_spec: {
  111. narrative_job: `job-${index + 1}`,
  112. composition_family: ["centered hero", "diagonal material field", "wide room depth", "single-space feature relation", "multi-angle grid", "human action frame", "continuous usage moment"][index],
  113. shot_scale: ["full product", "medium product", "wide environment", "detail and whole", "multi-view", "human medium-wide", "context close-medium"][index],
  114. camera_angle: ["eye level", "low oblique", "high wide", "side close", "three-quarter grid", "shoulder height", "top-oblique context"][index],
  115. camera_axis: ["front", "low", "three_quarter_left", "side", "three_quarter_right", "front", "top"][index],
  116. framing_mode: ["full_product", "detail", "product_in_context", "full_product", "multi_panel", "human_action", "product_in_context"][index],
  117. product_pose: ["upright", "detail_crop", "upright", "arranged_sequence", "multi_view", "held", "laid_flat"][index],
  118. product_placement: `distinct placement ${index + 1}`,
  119. product_occupancy_pct: [70, 45, 25, 50, 60, 20, 55][index],
  120. depth_structure: `distinct depth structure ${index + 1}`,
  121. background_family: ["pure seamless", "material field", "lived-in room", "feature stage", "neutral grid", "human environment", "continuous context"][index],
  122. lighting_family: ["even studio", "directional material", "window ambient", "edge definition", "flat comparative", "motivated environmental", "clear contextual"][index],
  123. interaction_mode: ["single accurate product", "material relation", "environment placement", "feature relation", "multiple exterior views", "human action", "single moment relation"][index],
  124. information_density: ["low", "medium", "medium", "medium", "high", "medium", "medium"][index],
  125. },
  126. prompt_modules: modules,
  127. generation_prompt: compilePrompt(modules),
  128. negative_prompt: "deformation, watermark",
  129. overlay_copy: [],
  130. reference_images: [reference],
  131. model_parameters: { adapter: "jimeng_img_v4", width: 2048, height: 2048, scale: 0.6, force_single: true },
  132. acceptance_checks: ["product identity preserved", "decision task is visible"],
  133. };
  134. }),
  135. };
  136. }