""" 专业玉雕设计提示词构建器(数据库版) 从数据库 prompt_templates + prompt_mappings 读取配置,支持后台热更新 """ import logging from typing import Optional, Dict, List from ..database import SessionLocal from ..models.prompt_template import PromptTemplate, PromptMapping logger = logging.getLogger(__name__) # ============================================================ # 品类视角配置(保留硬编码,因为与业务流程强关联) # ============================================================ CATEGORY_VIEWS: Dict[str, List[str]] = { "牌子": ["效果图", "正面图", "背面图"], "珠子": ["效果图", "正面图"], "手把件": ["效果图", "正面图", "侧面图", "背面图"], "雕刻件": ["效果图", "正面图", "侧面图", "背面图"], "摆件": ["效果图", "正面图", "侧面图", "背面图"], "手镯": ["效果图", "正面图", "侧面图"], "耳钉": ["效果图", "正面图"], "耳饰": ["效果图", "正面图"], "手链": ["效果图", "正面图"], "项链": ["效果图", "正面图"], "戒指": ["效果图", "正面图", "侧面图"], "表带": ["效果图", "正面图"], "随形": ["效果图", "正面图", "侧面图", "背面图"], } # ============================================================ # 品类专属背面描述(不同品类的背面特征差异很大) # ============================================================ BACK_VIEW_HINTS: Dict[str, str] = { "牌子": ( "IMPORTANT: The reverse/back side of a jade pendant plaque is traditionally a smooth, flat, polished surface. " "It may have a brief inscription or seal mark, but it must NOT have any carved figure, face, or decorative relief pattern. " "The back is plain and minimalist. Do NOT mirror or duplicate the front carving on the back." ), "手把件": ( "The back of this hand-held jade piece continues the same sculptural form as the front. " "It is part of the same three-dimensional object, showing the natural continuation of the carving from the rear angle." ), "雕刻件": ( "The back of this carved jade piece shows the rear of the same three-dimensional sculpture. " "The carving continues around the object naturally, not a separate or different design." ), "摆件": ( "The back of this jade display piece shows the rear of the same three-dimensional artwork. " "The form and carving continue naturally around the object." ), "随形": ( "The back of this free-form jade piece shows the natural stone surface from the rear. " "The organic shape continues naturally, the back may show more of the raw jade texture." ), } # 品类专属侧面描述 SIDE_VIEW_HINTS: Dict[str, str] = { "牌子": ( "The side/edge view of a jade pendant plaque shows its thin, flat profile. " "The plaque is typically 5-10mm thick, showing the edge thickness and any subtle edge carving." ), } def _load_mappings(mapping_type: str) -> Dict[str, str]: """从数据库加载指定类型的映射字典""" try: db = SessionLocal() try: rows = db.query(PromptMapping).filter( PromptMapping.mapping_type == mapping_type ).order_by(PromptMapping.sort_order).all() return {r.cn_key: r.en_value for r in rows} finally: db.close() except Exception as e: logger.warning(f"加载映射 {mapping_type} 失败: {e}") return {} def _load_template(template_key: str, default: str = "") -> str: """从数据库加载模板""" try: db = SessionLocal() try: tpl = db.query(PromptTemplate).filter( PromptTemplate.template_key == template_key ).first() if tpl: return tpl.template_value finally: db.close() except Exception as e: logger.warning(f"加载模板 {template_key} 失败: {e}") return default def get_views_for_category(category_name: str) -> List[str]: """获取品类对应的视角列表""" return CATEGORY_VIEWS.get(category_name, ["效果图", "正面图"]) def build_prompt( category_name: str, view_name: str, sub_type_name: Optional[str] = None, color_name: Optional[str] = None, user_prompt: Optional[str] = None, carving_technique: Optional[str] = None, design_style: Optional[str] = None, motif: Optional[str] = None, size_spec: Optional[str] = None, surface_finish: Optional[str] = None, usage_scene: Optional[str] = None, ) -> str: """ 构建专业英文生图提示词(从数据库读取映射和模板) 业务逻辑:用户参数 → 中英映射 → 填入模板 → 最终prompt """ # 从数据库加载所有映射 category_map = _load_mappings("category") color_map = _load_mappings("color") view_map = _load_mappings("view") carving_map = _load_mappings("carving") style_map = _load_mappings("style") motif_map = _load_mappings("motif") finish_map = _load_mappings("finish") scene_map = _load_mappings("scene") sub_type_map = _load_mappings("sub_type") # 加载模板 quality_suffix = _load_template("quality_suffix", "professional jewelry product photography, studio lighting setup, pure white background, ultra-detailed, sharp focus, 8K resolution, photorealistic rendering, high-end commercial quality") default_color = _load_template("default_color", "natural Hetian nephrite jade with warm luster") # 构建各部分 parts = [] # 1. 品类主体 subject = category_map.get(category_name, f"Chinese Hetian nephrite jade {category_name}") parts.append(subject) # 2. 子类型 if sub_type_name: sub_detail = sub_type_map.get(sub_type_name, sub_type_name) parts.append(sub_detail) # 3. 颜色 if color_name: color_desc = color_map.get(color_name, f"{color_name} colored nephrite jade") parts.append(color_desc) else: parts.append(default_color) # 4. 题材纹样 if motif: motif_desc = motif_map.get(motif, f"{motif} themed design") parts.append(f"featuring {motif_desc}") # 5. 雕刻工艺 if carving_technique: tech_desc = carving_map.get(carving_technique, carving_technique) parts.append(tech_desc) # 6. 设计风格 if design_style: style_desc = style_map.get(design_style, design_style) parts.append(style_desc) # 7. 表面处理 if surface_finish: finish_desc = finish_map.get(surface_finish, surface_finish) parts.append(finish_desc) # 8. 用途场景 if usage_scene: scene_desc = scene_map.get(usage_scene, usage_scene) parts.append(scene_desc) # 9. 尺寸 if size_spec: parts.append(f"size approximately {size_spec}") # 10. 用户描述 if user_prompt: parts.append(f"design concept: {user_prompt}") # 11. 视角 view_desc = view_map.get(view_name, "three-quarter view") parts.append(view_desc) # 12. 品类专属视角描述(背面/侧面特征) if view_name == "背面图" and category_name in BACK_VIEW_HINTS: parts.append(BACK_VIEW_HINTS[category_name]) elif view_name == "侧面图" and category_name in SIDE_VIEW_HINTS: parts.append(SIDE_VIEW_HINTS[category_name]) # 13. 质量后缀 parts.append(quality_suffix) return ", ".join(parts)