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)