fix(#2186): portrait_prompt智能回填+few-shot示例,服装发型还原增强 #2186

Merged
auto-approve-bot merged 2 commits from fix/portrait-prompt-smart-fallback into develop 2026-10-05 01:03:16 +08:00
2 changed files with 120 additions and 2 deletions
+116 -1
View File
@@ -444,6 +444,121 @@ def _analyze_single_image(
_parts.append(f"{_skin}肤色")
_parts.append(f"{_face}脸型")
_parts.append(f"身着{_outfit}")
if _pose != "无法判断":
_parts.append(f"姿态{_pose}")
if _expr != "无法判断":
_parts.append(f"表情{_expr}")
else:
_parts.append("表情自然")
# #2186: 智能回填——VLM有时省略hair/outfit等外貌属性,但product.name/features/colors里已有相关信息
# 从product名字和features中提取服装关键词回填outfit
if _outfit in ("日常服装", "无法判断"):
for _ppn in product_nodes:
_pn = (_ppn.get("attrs") or {}).get("name", "") or ""
_pf = (_ppn.get("attrs") or {}).get("features", "") or ""
_ptxt = _pn + " " + _pf
# 服装关键词识别(常见上装/下装/裙装/套装)
_cloth_kws = [
"衬衫",
"T恤",
"毛衣",
"针织衫",
"卫衣",
"外套",
"西装",
"夹克",
"风衣",
"大衣",
"羽绒服",
"马甲",
"背心",
"连衣裙",
"半身裙",
"短裙",
"长裙",
"牛仔裤",
"休闲裤",
"西裤",
"运动裤",
"短裤",
"旗袍",
"汉服",
"制服",
"polo衫",
"POLO衫",
"针织",
"毛衫",
"开衫",
"帽衫",
"皮夹克",
"皮衣",
]
for _ckw in _cloth_kws:
if _ckw in _ptxt:
# 提取含关键词的短语(关键词前后4字)
_ci = _ptxt.find(_ckw)
_start = max(0, _ci - 6)
_end = min(len(_ptxt), _ci + len(_ckw) + 2)
_outfit_extract = _ptxt[_start:_end].strip(" ,,。.、")
# 清理掉品牌名/产品名词的干扰(只取服装描述部分)
_outfit_extract = re.sub(
r"^[\w一-龥]{0,2}(牌|品牌|的|款|女|男|新|装|大|小|长|短|厚|薄)",
"",
_outfit_extract,
)
if len(_outfit_extract) >= 2:
_outfit = _outfit_extract
break
if _outfit not in ("日常服装", "无法判断"):
break
# 从color标签中提取头发颜色回填hair
if _hair in ("自然发型", "无法判断"):
_hair_color = ""
_color_nodes = [n for n in nodes if n["tag"] == "color"]
_hair_kws_map = {
"黑": "黑色",
"棕": "棕色",
"金": "金色",
"栗": "栗色",
"红": "红色",
"白": "白色",
"灰": "灰色",
"蓝": "蓝色",
"黄": "黄色",
"紫": "紫色",
}
for _cn in _color_nodes:
_cname = (_cn.get("attrs") or {}).get("name", "") or ""
# 小占比颜色更可能是发色(非主色的小面积色),且名称含头发/黑/棕/金等
_ccov = 0.0
try:
_ccov = float((_cn.get("attrs") or {}).get("coverage", "0") or 0)
except Exception:
pass
for _hk, _hv in _hair_kws_map.items():
if _hk in _cname and _ccov < 0.3:
_hair_color = _hv
break
if _hair_color:
break
if _hair_color:
_hair = f"{_hair_color}头发"
else:
_hair = "自然发型"
# 重新拼装_parts(回填后)
_parts = []
if _gender != "无法判断":
_g = _gender + ("性" if not _gender.endswith("性") else "")
_parts.append(_g)
else:
_parts.append("成年人")
if _age != "无法判断":
_parts.append(_age)
_parts.append("人物")
_parts.append(_hair)
_parts.append(f"{_skin}肤色")
_parts.append(f"{_face}脸型")
_parts.append(f"身着{_outfit}")
if _pose != "无法判断":
_parts.append(f"姿态{_pose}")
if _expr != "无法判断":
@@ -452,7 +567,7 @@ def _analyze_single_image(
_parts.append("表情自然")
portrait_prompt = ",".join(_parts)
logger.info(
"[爆款视频] 图片 #%d 解析<people>: count=%d gender=%s age=%s hair=%s skin=%s face=%s outfit=%s pose=%s expr=%s → %s",
"[爆款视频] 图片 #%d 解析<people>(回填后): count=%d gender=%s age=%s hair=%s skin=%s face=%s outfit=%s pose=%s expr=%s → %s",
idx,
_count,
_gender,
+4 -1
View File
@@ -65,7 +65,10 @@ hair/skin_tone/face_shape/outfit四项绝对禁止填“无法判断”,必须
- outfit:必须描述可见穿着,如“米色翻领衬衫”“白色T恤”“黑色连衣裙”
即使局部被遮挡也要根据可见部分合理推断;确实看不清时按最接近的直观印象描述。
其他非人物属性看不到或无法判断时填“无法判断”,布尔值填false,不要留空标签。"""
其他非人物属性看不到或无法判断时填“无法判断”,布尔值填false,不要留空标签。
【有人物场景输出参考(女性手持商品示例,必须写全10个属性,禁止省略)】
<people has_person="true" count="1" gender="女" age_range="青年" hair="黑色齐肩直发" skin_tone="暖调自然肤色" face_shape="鹅蛋脸" outfit="米色翻领衬衫" pose="正面半身,手持商品" expression="面带微笑"/>"""
_IMAGE_ANALYSIS_USER = """请分析以下商品图片,共 {image_count} 张。
所属行业:{industry}