refactor: extract order helpers and stabilize first-image ack replies

This commit is contained in:
2026-03-01 15:30:56 +08:00
parent 55e6fd51ec
commit 54b1db17a7
3 changed files with 49 additions and 62 deletions

View File

@@ -3,6 +3,7 @@ from __future__ import annotations
import asyncio import asyncio
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional
from core.post_ops import record_deal_success from core.post_ops import record_deal_success
from core.order_helpers import parse_order_info
if TYPE_CHECKING: if TYPE_CHECKING:
from core.pydantic_ai_agent import AgentResponse, ConversationState, CustomerMessage, CustomerServiceAgent from core.pydantic_ai_agent import AgentResponse, ConversationState, CustomerMessage, CustomerServiceAgent
@@ -22,7 +23,7 @@ async def handle_order_notification(
_, order_block = agent._split_customer_text(message.msg) _, order_block = agent._split_customer_text(message.msg)
customer_text, _ = agent._split_customer_text(message.msg) customer_text, _ = agent._split_customer_text(message.msg)
order = agent._parse_order_info(order_block or message.msg) order = parse_order_info(order_block or message.msg)
pay_status = order.get("pay_status", "") pay_status = order.get("pay_status", "")
order_status = order.get("order_status", "") order_status = order.get("order_status", "")

38
core/order_helpers.py Normal file
View File

@@ -0,0 +1,38 @@
from __future__ import annotations
import re
from typing import Dict
def parse_order_info(msg: str) -> Dict[str, str]:
"""从系统订单消息中提取字段。"""
info: Dict[str, str] = {}
m = re.search(r"订单号[:]\s*(\d+)", msg or "")
if m:
info["order_id"] = m.group(1)
m = re.search(r"订单状态[:]\s*([^\s\[]+)", msg or "")
if m:
info["order_status"] = m.group(1).strip()
m = re.search(r"\[状态[:]\s*([^\]]+)\]", msg or "")
if m:
info["pay_status"] = m.group(1).strip()
m = re.search(r"金额[:]\s*([\d.]+)元", msg or "")
if m:
info["amount"] = m.group(1)
m = re.search(r"数量[:]\s*(\d+)", msg or "")
if m:
info["quantity"] = m.group(1)
m = re.search(r"(\d{4}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{2}:\d{2})", msg or "")
if m:
info["order_time"] = m.group(1).strip()
m = re.search(r"买家备注[:]\s*([^\n]+)", msg or "")
if m and m.group(1).strip():
info["buyer_note"] = m.group(1).strip()
return info
def order_instruction(pay_status: str, order_status: str) -> str:
paid_keywords = ["等待发货", "已付款", "付款成功", "买家已付款"]
if any(kw in (pay_status or "") or kw in (order_status or "") for kw in paid_keywords):
return "【已付款-必须回复】客户已付款,立刻自然回复确认收款并告知马上安排。"
return "【仅系统通知-无需回复客户】这是系统订单通知,不需要回复客户任何内容,直接跳过。"

View File

@@ -31,6 +31,7 @@ from core.order_flow import handle_order_notification
from core.ai_reply_flow import execute_ai_turn from core.ai_reply_flow import execute_ai_turn
from core.reply_finalize_flow import finalize_ai_reply from core.reply_finalize_flow import finalize_ai_reply
from core.prompt_flow import build_prompt_bundle from core.prompt_flow import build_prompt_bundle
from core.order_helpers import parse_order_info, order_instruction as build_order_instruction
load_dotenv() load_dotenv()
@@ -443,12 +444,12 @@ class CustomerServiceAgent:
if scene == "collect_ack" and len(state.pending_image_urls) == 1: if scene == "collect_ack" and len(state.pending_image_urls) == 1:
first_ack = [ first_ack = [
"收到了,我先看一下哈,稍等哈", "收到了,我先看一下哈,稍等哈",
"这张我收到了,我先看下,等我一下哈", "这张我收到了,我先看下,等我一下哈",
"收到这张了,我先过一眼,稍等哈", "收到这张了,我先过一眼,稍等哈",
"我先看这张哈,稍等我一下", "我先看这张哈,稍等我一下",
"图我收到了,我先看一眼,马上回你哈", "图我收到了,我先看一眼,稍等我回你哈",
"这张先记上了,我先看下细节,稍等哈", "这张先记上了,我先看下细节,稍等哈",
"收到哈,我先过一遍这张,等我会儿", "收到哈,我先过一遍这张,等我会儿",
"我先看这张效果,稍等一下哈", "我先看这张效果,稍等一下哈",
"图到了,我先看下清晰度,稍等哈", "图到了,我先看下清晰度,稍等哈",
"这张我先看着,稍等我一下就回你", "这张我先看着,稍等我一下就回你",
@@ -914,7 +915,7 @@ class CustomerServiceAgent:
@self.agent_order.tool @self.agent_order.tool
async def handle_order(ctx: RunContext[AgentDeps], raw_msg: str = "") -> str: async def handle_order(ctx: RunContext[AgentDeps], raw_msg: str = "") -> str:
try: try:
info = self._parse_order_info(raw_msg or "") info = parse_order_info(raw_msg or "")
paid_kw = ["等待发货", "已付款", "付款成功", "买家已付款"] paid_kw = ["等待发货", "已付款", "付款成功", "买家已付款"]
if any(k in (info.get("pay_status", "") or "") for k in paid_kw) or any(k in (info.get("order_status", "") or "") for k in paid_kw): if any(k in (info.get("pay_status", "") or "") for k in paid_kw) or any(k in (info.get("order_status", "") or "") for k in paid_kw):
return "已安排,稍后发你" return "已安排,稍后发你"
@@ -1900,59 +1901,6 @@ class CustomerServiceAgent:
except Exception as e: except Exception as e:
print(f"[Agent] 订单金额核查失败: {e}") print(f"[Agent] 订单金额核查失败: {e}")
def _parse_order_info(self, msg: str) -> dict:
"""从系统订单消息中提取所有字段"""
import re
info = {}
m = re.search(r'订单号[:]\s*(\d+)', msg)
if m:
info['order_id'] = m.group(1)
# 订单大状态(新订单/交易成功/交易关闭等)
m = re.search(r'订单状态[:]\s*([^\s\[]+)', msg)
if m:
info['order_status'] = m.group(1).strip()
# 支付细状态(等待买家付款/等待发货/交易完成等)
m = re.search(r'\[状态[:]\s*([^\]]+)\]', msg)
if m:
info['pay_status'] = m.group(1).strip()
# 金额
m = re.search(r'金额[:]\s*([\d.]+)元', msg)
if m:
info['amount'] = m.group(1)
# 数量
m = re.search(r'数量[:]\s*(\d+)', msg)
if m:
info['quantity'] = m.group(1)
# 时间格式2026-2-24 19:52:52
m = re.search(r'(\d{4}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{2}:\d{2})', msg)
if m:
info['order_time'] = m.group(1).strip()
# 买家备注
m = re.search(r'买家备注[:]\s*([^\n]+)', msg)
if m and m.group(1).strip():
info['buyer_note'] = m.group(1).strip()
return info
def _get_order_instruction(self, pay_status: str, order_status: str) -> str:
"""
根据订单状态生成 AI 指令。
只有「已付款」才需要回复客户,其他状态一律静默。
"""
paid_keywords = ["等待发货", "已付款", "付款成功", "买家已付款"]
if any(kw in pay_status or kw in order_status for kw in paid_keywords):
return "【已付款-必须回复】客户已付款,立刻自然回复确认收款并告知马上安排。"
else:
# 所有其他状态(待付款、交易完成、关闭等)静默处理
return "【仅系统通知-无需回复客户】这是系统订单通知,不需要回复客户任何内容,直接跳过。"
def _extract_image_url(self, msg: str) -> str: def _extract_image_url(self, msg: str) -> str:
"""从消息中提取图片URL兼容纯URL和 text#*#url 两种格式""" """从消息中提取图片URL兼容纯URL和 text#*#url 两种格式"""
urls = self._extract_image_urls(msg) urls = self._extract_image_urls(msg)
@@ -2653,7 +2601,7 @@ class CustomerServiceAgent:
has_order = bool(order_block) has_order = bool(order_block)
if has_order: if has_order:
order = self._parse_order_info(order_block) order = parse_order_info(order_block)
if order.get('order_id'): if order.get('order_id'):
state.last_order_id = order['order_id'] state.last_order_id = order['order_id']
stage_info += f"\n【订单号】{order['order_id']}" stage_info += f"\n【订单号】{order['order_id']}"
@@ -2707,7 +2655,7 @@ class CustomerServiceAgent:
order_paid = False order_paid = False
order_unpaid = False order_unpaid = False
if has_order: if has_order:
order = self._parse_order_info(order_block) order = parse_order_info(order_block)
paid_kws = ["等待发货", "已付款", "付款成功", "买家已付款"] paid_kws = ["等待发货", "已付款", "付款成功", "买家已付款"]
unpaid_kws = ["等待买家付款", "待付款", "未付款"] unpaid_kws = ["等待买家付款", "待付款", "未付款"]
ps = order.get('pay_status', '') ps = order.get('pay_status', '')
@@ -2774,8 +2722,8 @@ class CustomerServiceAgent:
# ── 附加订单信息(不覆盖客户问题的优先级)── # ── 附加订单信息(不覆盖客户问题的优先级)──
if has_order: if has_order:
order = self._parse_order_info(order_block) order = parse_order_info(order_block)
order_instruction = self._get_order_instruction( order_instruction = build_order_instruction(
order.get('pay_status', ''), order.get('pay_status', ''),
order.get('order_status', '') order.get('order_status', '')
) )