feat(vision): 人物图片分析质量提升 v5(assembler字段扩充+migration 098 seed) #2218

Merged
xiaoxia merged 2 commits from feature/vision-v5-person-quality into develop 2026-10-06 10:56:09 +08:00
3 changed files with 147 additions and 30 deletions
File diff suppressed because one or more lines are too long
@@ -420,7 +420,7 @@ def _assemble_v4(idx: int, fj: dict, ocr_texts: list[str]) -> dict[str, Any]:
# 人物类
if vtype == "person" or has_person:
# 取第一个人物信息(v4 schema人物信息在顶层)
# 取第一个人物信息(v5 schema人物信息在顶层)
person_info = fj
# 兼容people嵌套
ppl = fj.get("people")
@@ -429,58 +429,75 @@ def _assemble_v4(idx: int, fj: dict, ocr_texts: list[str]) -> dict[str, Any]:
has_person = True
portrait_prompt = _build_portrait_prompt_from_v4(person_info)
name = person_info.get("upper_wear") or "人物穿搭"
if "连衣裙" in name:
pass
outfit_style = person_info.get("outfit_style") or ""
upper = person_info.get("upper_wear") or ""
lower = person_info.get("lower_wear") or ""
dress = person_info.get("dress_wear") or ""
outer = person_info.get("outerwear") or ""
if dress:
name = str(dress)[:25]
elif outer and upper:
name = f"{outer}+{upper}"[:30]
elif upper:
name = (str(upper) + (f"+{lower}" if lower else ""))[:30]
else:
lower = person_info.get("lower_wear") or ""
if lower:
name = f"{name}+{lower}"
name = "人物穿搭"
brand = "无法判断"
category = "服饰"
outfit_parts = []
for k in ("upper_wear", "lower_wear", "dress_color", "upper_color", "lower_color", "outfit_style"):
category = "人物穿搭"
# appearance: 外套+上衣+下装/裙+鞋+包+发型+妆容
app_parts = []
for k in ("outerwear", "upper_wear", "lower_wear", "dress_wear", "shoes", "bag", "hairstyle", "makeup"):
v = person_info.get(k)
if v and v not in ("null", None):
outfit_parts.append(str(v))
appearance = "、".join(outfit_parts) if outfit_parts else "人像穿搭整体造型"
# key_features: 穿搭特征+配饰
if v and v not in ("null", None, "无明显妆容"):
app_parts.append(str(v))
appearance = ";".join(app_parts) if app_parts else "人像穿搭整体造型"
# key_features: 服装+配饰+拍摄信息
kf = []
for k in (
"outfit_style",
"upper_wear",
"lower_wear",
"upper_color",
"lower_color",
"dress_wear",
"outerwear",
"shoes",
"bag",
"hairstyle",
"expression",
"pose",
"outfit_style",
):
v = person_info.get(k)
if v and v not in ("null", None, "无法判断"):
kf.append(str(v))
acc = person_info.get("accessories") or []
if isinstance(acc, list):
kf.extend(str(a) for a in acc if a)
for a in acc:
if a and str(a) not in kf:
kf.append(str(a))
elif isinstance(acc, str) and acc:
kf.append(acc)
for k in ("shot_type", "camera_angle", "lighting", "atmosphere"):
v = person_info.get(k)
if v and v not in ("null", None):
kf.append(str(v))
if text_on_package:
kf.append(f"画面文字: {'/'.join(text_on_package[:3])}")
kf = kf[:6] or ["无法判断"]
summary = (person_info.get("outfit_style") or "") + (person_info.get("upper_wear") or "穿搭")
if not summary or summary == "穿搭":
kf.append(f"文字:{'/'.join(text_on_package[:3])}")
kf = kf[:8] or ["无法判断"]
summary = (outfit_style + " " if outfit_style and outfit_style not in name else "") + name[:25]
if not summary.strip():
summary = "人物穿搭"
return {
"name": name[:30],
"brand": brand,
"category": category,
"appearance": appearance,
"appearance": appearance[:400],
"packaging": "人物形象无包装",
"text_on_package": text_on_package,
"key_features": kf,
"scene": scene,
"mood": mood,
"portrait_prompt": portrait_prompt,
"summary": summary[:40],
"_source": "v2_fast_json_v4",
"portrait_prompt": portrait_prompt[:300],
"summary": summary[:50],
"_source": "v2_fast_json_v5",
}
# 商品类
+4 -4
View File
@@ -137,18 +137,18 @@ V4_PERSON: dict[str, Any] = {
def test_assemble_v4_person() -> None:
r = assembler.assemble_result(0, V4_PERSON, [])
assert REQUIRED_KEYS <= set(r.keys())
assert r["category"] == "服饰"
assert r["category"] == "人物穿搭"
assert r["_source"] == "v2_fast_json_v5"
assert "T恤" in r["name"]
assert "阔腿裤" in r["name"]
assert "年轻女性" in r["portrait_prompt"]
assert "项链" in r["portrait_prompt"]
assert isinstance(r["key_features"], list) and len(r["key_features"]) <= 6
assert isinstance(r["key_features"], list) and len(r["key_features"]) <= 8
def test_assemble_v4_person_people_nested() -> None:
fj = {"type": "person", "people": {**V4_PERSON, "has_person": True}}
r = assembler.assemble_result(0, fj, [])
assert r["category"] == "服饰"
assert r["category"] == "人物穿搭"
assert "年轻女性" in r["portrait_prompt"]