fix: dedupe wechat chat history and avoid duplicate outbound chat logging

This commit is contained in:
2026-02-28 20:18:29 +08:00
parent 40cb03dd28
commit 1a5b4a4be6
3 changed files with 34 additions and 16 deletions

View File

@@ -515,6 +515,10 @@ class CustomerServiceAgent:
try: try:
from image.image_analyzer import image_analyzer from image.image_analyzer import image_analyzer
result = await image_analyzer.analyze(image_url) result = await image_analyzer.analyze(image_url)
if result.get("feasibility") == "no" or result.get("risk") == "high":
return "该图风险高或不可做:不报价,建议换图或转人工评估。"
if not result.get("success", False):
return "图片识别异常:先不报价,建议客户重发更清晰图片。"
p = result.get("price_suggest", 20) p = result.get("price_suggest", 20)
try: try:
st = self._get_conversation_state(ctx.deps.from_id) st = self._get_conversation_state(ctx.deps.from_id)

View File

@@ -587,7 +587,8 @@ class QingjianAPIClient:
pass pass
reply = f"这张按{p}元,满意再拍" reply = f"这张按{p}元,满意再拍"
else: else:
reply = "这张我看了先按20元给你做" # 识别失败时不做兜底报价,避免把未识别图片误判为可做
reply = "这张我这边暂时识别不稳定,先不乱报价。你可以换一张更清晰的,我再给你准报价。"
await self.send_reply(data, reply) await self.send_reply(data, reply)
except Exception: except Exception:
pass pass
@@ -792,13 +793,6 @@ class QingjianAPIClient:
await asyncio.sleep(0.8) await asyncio.sleep(0.8)
logger.info(f"Agent 回复: {response.reply}") logger.info(f"Agent 回复: {response.reply}")
await self.send_reply(data, response.reply) await self.send_reply(data, response.reply)
# 记录客服回复
if _cid:
try:
_chat_log(_cid, response.reply, "out", customer_name=_name,
acc_id=data.get('acc_id', ''), platform=_plat)
except Exception:
pass
# 推送到企微:客户消息+AI回复成对 # 推送到企微:客户消息+AI回复成对
try: try:
from utils.wechat_chat_log import push_chat_to_wechat from utils.wechat_chat_log import push_chat_to_wechat
@@ -840,6 +834,25 @@ class QingjianAPIClient:
tasks = [image_analyzer.analyze(u) for u in urls] tasks = [image_analyzer.analyze(u) for u in urls]
results = await asyncio.gather(*tasks, return_exceptions=True) results = await asyncio.gather(*tasks, return_exceptions=True)
# 先做风险分流:多图中只要出现不可做/高风险,不进入报价
unsafe = []
dense_text_reject = []
for i, r in enumerate(results, 1):
if isinstance(r, dict) and r.get("success", False):
if r.get("feasibility") == "no" or r.get("risk") == "high":
unsafe.append(f"{i}")
note = str(r.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 self.send_reply(data, reply)
return
pairs = [] pairs = []
for u, r in zip(urls, results): for u, r in zip(urls, results):
if isinstance(r, dict) and r.get("success", False): if isinstance(r, dict) and r.get("success", False):
@@ -862,7 +875,7 @@ class QingjianAPIClient:
except Exception: except Exception:
pass pass
if not pairs: if not pairs:
await self.send_reply(data, "这组图我看了先按20元一张给你做") await self.send_reply(data, "这组图我这边暂时识别不稳定,先不乱报价。你可以换清晰图再发我。")
return return
composite = _detect_composite_request() composite = _detect_composite_request()
composite_fee = 5 if composite else 0 composite_fee = 5 if composite else 0
@@ -879,7 +892,7 @@ class QingjianAPIClient:
except Exception as e: except Exception as e:
logger.error(f"多图分析失败: {e}") logger.error(f"多图分析失败: {e}")
try: try:
await self.send_reply(data, "这组图我看了先按20元一张给你做") await self.send_reply(data, "这组图我这边暂时识别异常,先不乱报价。你可以稍后再发我。")
except Exception: except Exception:
pass pass
def _msg_requests_external_contact(self, msg: str) -> bool: def _msg_requests_external_contact(self, msg: str) -> bool:
@@ -1321,11 +1334,6 @@ class QingjianAPIClient:
} }
await asyncio.sleep(0.5) await asyncio.sleep(0.5)
await self.send_reply(fake_data, response.reply) await self.send_reply(fake_data, response.reply)
try:
_chat_log(customer_id, response.reply, "out",
acc_id=acc_id, platform=acc_type)
except Exception:
pass
logger.info(f"[Workflow] AI 通知已发送: {response.reply}") logger.info(f"[Workflow] AI 通知已发送: {response.reply}")
except Exception as e: except Exception as e:
logger.error(f"[Workflow] AI 通知生成失败: {e}") logger.error(f"[Workflow] AI 通知生成失败: {e}")

View File

@@ -83,11 +83,17 @@ async def push_chat_to_wechat(
# 附带近期对话,保持连贯 # 附带近期对话,保持连贯
recent = _get_recent_conversation(customer_id, acc_id, last_n=8) recent = _get_recent_conversation(customer_id, acc_id, last_n=8)
last_line = None
for m in recent: for m in recent:
role = customer_id if m.get("direction") == "in" else "客服" role = customer_id if m.get("direction") == "in" else "客服"
msg = _truncate((m.get("message") or "").strip(), 120) msg = _truncate((m.get("message") or "").strip(), 120)
if msg: if msg:
lines.append(f"{role}{msg}") line = f"{role}{msg}"
# 防止日志中的重复记录在企微里连续刷屏
if line == last_line:
continue
lines.append(line)
last_line = line
# 当前回复(可能已在 recent 中有客户消息,客服回复是新的) # 当前回复(可能已在 recent 中有客户消息,客服回复是新的)
lines.append(f"客服:{reply_msg or '(无回复)'}") lines.append(f"客服:{reply_msg or '(无回复)'}")