feat: upgrade客服多店铺分流、批量报价与稳定性防护

This commit is contained in:
2026-02-28 18:52:31 +08:00
parent c39840fe15
commit 46143be86c
16 changed files with 1329 additions and 37 deletions

View File

@@ -239,6 +239,11 @@ class ImageAnalyzer:
# 最短等待时间即使AI极快返回也等这么久看起来像真人在找
MIN_WAIT_SECONDS = 4
DENSE_TEXT_SUBJECT_KEYWORDS = (
"宣传栏", "公告栏", "展板", "海报墙", "通知栏", "知识栏", "制度牌", "公示栏", "墙报", "密密麻麻",
"word wall", "poster wall", "bulletin board",
)
async def analyze(self, image_path: str) -> dict:
"""
异步分析图片复杂度(使用火山引擎 /responses 接口)。
@@ -519,6 +524,8 @@ class ImageAnalyzer:
sensitive = p(content, "敏感内容:", "敏感内容:").lower().strip()
flatness = p(content, "平整度:", "平整度:").lower().strip() # flat|mild|rough
has_text = p(content, "含文字:", "含文字:").lower().strip()
text_amount = p(content, "文字数量:", "文字数量:").strip()
text_layer_need = p(content, "文字分层需求:", "文字分层需求:").lower().strip()
has_face = p(content, "含人脸:", "含人脸:").lower().strip()
has_shadow = p(content, "阴影:", "阴影:").lower().strip()
reason = p(content, "原因:", "原因:")
@@ -534,11 +541,22 @@ class ImageAnalyzer:
if has_face not in ("yes", "no"):
has_face = "no"
valid_text_amounts = {"none", "少量 (1-10 字)", "中量 (11-50 字)", "大量 (51-200 字)", "极多 (200 字以上)"}
if text_amount not in valid_text_amounts:
text_amount = "none"
if text_layer_need not in ("yes", "no"):
text_layer_need = "no"
if risk not in ("none", "low", "high"):
risk = "none"
if perspective not in ("no", "mild", "strong"):
perspective = "no"
# 识别“密集文字场景”关键词(中文 + 英文兜底)
dense_text_scene = any(
kw in ((subject or "") + " " + (proc_type or "") + " " + (reason or "")).lower()
for kw in self.DENSE_TEXT_SUBJECT_KEYWORDS
)
# 校验比例合法性
valid_ratios = {"1:1", "9:16", "16:9", "3:4", "4:3", "3:2", "2:3", "5:4", "4:5"}
if aspect_ratio not in valid_ratios:
@@ -556,11 +574,11 @@ class ImageAnalyzer:
if has_text == "yes":
if complexity == "simple":
# 简单但含文字 → 提升到 normal 价格
price_min, price_max = self.PRICE_MAP["normal"]
price_min, price_max, _ = self.PRICE_MAP["normal"]
reason = "含文字,需精细处理"
elif complexity == "normal":
# normal 含文字 → 提升到 complex 价格
price_min, price_max = self.PRICE_MAP["complex"]
price_min, price_max, _ = self.PRICE_MAP["complex"]
reason = "含文字,需精细处理"
# complex/hard 保持原价,已经够高
# 建议报价complex/hard 取固定值simple/normal 取中间且必须为5的整数倍
@@ -605,6 +623,14 @@ class ImageAnalyzer:
price_suggest = 80
reason += " | 大量文字分层"
# 硬规则:密集文字类图片不接单(知识宣传栏/公告栏等)
if text_amount in ["大量 (51-200 字)", "极多 (200 字以上)"] or dense_text_scene:
feasibility = "no"
risk = "high"
note = "文字内容过于密集(如宣传栏/公告栏),暂不接单处理"
reason = (reason or "文字密集") + " | 密集文字场景不接单"
price_suggest = 0
# 确保是 5 的倍数
price_suggest = round(price_suggest / 5) * 5
@@ -649,6 +675,10 @@ class ImageAnalyzer:
def _fallback(self, reason: str) -> dict:
"""识别失败时的默认结果(返回 normal让人工判断"""
print(f"[ImageAnalyzer] 识别失败,使用默认值: {reason}")
text_amount = "none"
text_layer_need = "no"
text_surcharge = 0
layer_surcharge = 0
return {
"complexity": "normal",
"reason": reason,