129 lines
6.5 KiB
Python
129 lines
6.5 KiB
Python
import asyncio
|
|
import logging
|
|
|
|
logger = logging.getLogger("cs_agent")
|
|
|
|
|
|
async def handle_single_image_quote(client, data: dict, url: str):
|
|
try:
|
|
from image.image_analyzer import image_analyzer
|
|
|
|
result = await image_analyzer.analyze(url)
|
|
if isinstance(result, dict) and result.get("success", False):
|
|
if result.get("feasibility") == "no" or result.get("risk") == "high":
|
|
note = str(result.get("note", "") or "")
|
|
if "文字内容过于密集" in note or "密集文字" in note:
|
|
reply = "这类文字太密的图我们这边不接单,抱歉哈。你要是简化后再发我可以继续看。"
|
|
else:
|
|
reply = "这张处理风险比较高,我这边先不直接接,建议转人工评估更稳。"
|
|
await client.send_reply(data, reply)
|
|
return
|
|
|
|
from config.config import MIN_PRICE_FLOOR
|
|
price = result.get("price_suggest", 20)
|
|
floor_dyn = result.get("price_min", MIN_PRICE_FLOOR)
|
|
floor = max(MIN_PRICE_FLOOR, int(floor_dyn) if isinstance(floor_dyn, (int, float)) else MIN_PRICE_FLOOR)
|
|
price = max(floor, round(price / 5) * 5)
|
|
try:
|
|
from db.customer_db import db as _db
|
|
_db.update_last_min_price(data.get('from_id', ''), floor)
|
|
except Exception:
|
|
logger.debug("更新单图最低价失败", exc_info=True)
|
|
reply = f"这张按{price}元,满意再拍"
|
|
else:
|
|
# 识别失败时不做兜底报价,避免把未识别图片误判为可做
|
|
reply = "这张我这边暂时识别不稳定,先不乱报价。你可以换一张更清晰的,我再给你准报价。"
|
|
await client.send_reply(data, reply)
|
|
except Exception:
|
|
logger.exception("单图分析流程失败")
|
|
|
|
|
|
async def handle_multi_image_quote(client, data: dict, urls: list):
|
|
try:
|
|
from image.image_analyzer import image_analyzer
|
|
|
|
def _detect_composite_request() -> bool:
|
|
try:
|
|
from db.chat_log_db import get_recent_conversation
|
|
recent = get_recent_conversation(
|
|
customer_id=data.get('from_id', ''),
|
|
acc_id=data.get('acc_id', ''),
|
|
limit=8,
|
|
)
|
|
keywords = ("抓到", "放到", "合成", "融合", "嵌到", "换到", "替换", "P到", "抠出来放到")
|
|
for item in recent:
|
|
msg = (item.get("message") or "")
|
|
if any(k in msg for k in keywords):
|
|
return True
|
|
except Exception:
|
|
logger.debug("检测合成需求失败,按非合成处理", exc_info=True)
|
|
return False
|
|
|
|
tasks = [image_analyzer.analyze(u) for u in urls]
|
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
|
|
# 先做风险分流:多图中只要出现不可做/高风险,不进入报价
|
|
unsafe = []
|
|
dense_text_reject = []
|
|
for i, result in enumerate(results, 1):
|
|
if isinstance(result, dict) and result.get("success", False):
|
|
if result.get("feasibility") == "no" or result.get("risk") == "high":
|
|
unsafe.append(f"图{i}")
|
|
note = str(result.get("note", "") or "")
|
|
if "文字内容过于密集" in note or "密集文字" in note:
|
|
dense_text_reject.append(f"图{i}")
|
|
|
|
if unsafe:
|
|
if dense_text_reject and len(dense_text_reject) == len(unsafe):
|
|
reply = "这类文字太密的图我们这边不接单,抱歉哈。你要是简化后再发我可以继续看。"
|
|
else:
|
|
reply = f"这批里{'、'.join(unsafe)}处理风险较高,我这边先不直接接,建议转人工评估更稳。"
|
|
await client.send_reply(data, reply)
|
|
return
|
|
|
|
pairs = []
|
|
for u, result in zip(urls, results):
|
|
if isinstance(result, dict) and result.get("success", False):
|
|
from config.config import MIN_PRICE_FLOOR
|
|
floor_dyn = result.get("price_min", MIN_PRICE_FLOOR)
|
|
floor = max(MIN_PRICE_FLOOR, int(floor_dyn) if isinstance(floor_dyn, (int, float)) else MIN_PRICE_FLOOR)
|
|
price = max(floor, round(result.get("price_suggest", 20) / 5) * 5)
|
|
pairs.append((u, price, result.get("category", ""), result.get("megapixels", 0.0)))
|
|
try:
|
|
if pairs:
|
|
floors = []
|
|
for _u, result in zip(urls, results):
|
|
if isinstance(result, dict) and result.get("success", False):
|
|
from config.config import MIN_PRICE_FLOOR
|
|
floor_dyn = result.get("price_min", MIN_PRICE_FLOOR)
|
|
floor = max(MIN_PRICE_FLOOR, int(floor_dyn) if isinstance(floor_dyn, (int, float)) else MIN_PRICE_FLOOR)
|
|
floors.append(floor)
|
|
if floors:
|
|
from db.customer_db import db as _db
|
|
_db.update_last_min_price(data.get('from_id', ''), min(floors))
|
|
except Exception:
|
|
logger.debug("更新多图最低价失败", exc_info=True)
|
|
|
|
if not pairs:
|
|
await client.send_reply(data, "这组图我这边暂时识别不稳定,先不乱报价。你可以换清晰图再发我。")
|
|
return
|
|
|
|
composite = _detect_composite_request()
|
|
composite_fee = 5 if composite else 0
|
|
avg_raw = sum(p for _, p, _, _ in pairs) / len(pairs)
|
|
from config.config import MIN_PRICE_FLOOR
|
|
avg_price = max(MIN_PRICE_FLOOR, round((avg_raw + composite_fee) / 5) * 5)
|
|
top_price = max(MIN_PRICE_FLOOR, max(pairs, key=lambda x: x[1])[1] + composite_fee)
|
|
count = len(pairs)
|
|
if composite:
|
|
reply = f"这组{count}张我看了,按{avg_price}元一张;合成那张{top_price}元,满意再拍"
|
|
else:
|
|
reply = f"这组{count}张我看了,按{avg_price}元一张;复杂那张{top_price}元,满意再拍"
|
|
await client.send_reply(data, reply)
|
|
except Exception as e:
|
|
logger.error("多图分析失败: %s", e)
|
|
try:
|
|
await client.send_reply(data, "这组图我这边暂时识别异常,先不乱报价。你可以稍后再发我。")
|
|
except Exception:
|
|
logger.debug("多图分析失败后的兜底回复发送失败", exc_info=True)
|