落地转人工:三次补问或明确接管后出入口,真正转人工后冻结本票并允许新开询价。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -22,9 +22,13 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _front_bookmark(sess) -> bool:
|
||||
"""补问/核对手稿优先于已出票旧书签。空的 need_mode 不算(那是丢会话后的误伤)。"""
|
||||
"""补问/核对手稿优先于已出票旧书签。空的 need_mode 不算(那是丢会话后的误伤)。已转人工的票也不再当当前询价。"""
|
||||
if sess is None:
|
||||
return False
|
||||
from agent.policy.handoff_human import is_handoff_frozen
|
||||
|
||||
if is_handoff_frozen(sess):
|
||||
return False
|
||||
phase = (sess.phase or "").strip()
|
||||
line = (sess.business_line or "").upper()
|
||||
if phase == "need_mode" and not line:
|
||||
@@ -32,16 +36,41 @@ def _front_bookmark(sess) -> bool:
|
||||
return phase in {"clarify", "need_mode", "need_land_options", "wait_confirm"}
|
||||
|
||||
|
||||
def should_resume_other_as_inquiry(message: InboundMessage) -> bool:
|
||||
"""
|
||||
A 把补问短答标成闲聊时,仍续填当前询价。
|
||||
|
||||
只拦还在问字段/选项/核对、未成交原因、转人工入口。
|
||||
已报价协同中不拦,避免「谢谢」被当成新询价。
|
||||
"""
|
||||
if not message.has_sender():
|
||||
return False
|
||||
engine = _pick_text_flow(
|
||||
sender_id=message.sender_id, text=message.content or ""
|
||||
)
|
||||
sess = engine.session_for_action(
|
||||
message.sender_id, message.raw, text=message.content or ""
|
||||
)
|
||||
if sess is None:
|
||||
return False
|
||||
phase = (sess.phase or "").strip()
|
||||
if phase in {"wait_lost_reason", "handoff_offer"}:
|
||||
return True
|
||||
return _front_bookmark(sess)
|
||||
|
||||
|
||||
def _pick_text_flow(*, sender_id: str, text: str, injected_mode: str = "", prefer_quoted: bool = False):
|
||||
"""
|
||||
按当前书签或本句运输方式选空运/海运/陆运流程。
|
||||
|
||||
陆运核对卡上的确定优先于旧海运书签,避免「确定」被海运/空运吃掉。
|
||||
A 已判成调价时交给当前已报价工单,避免旧海运书签抢走。
|
||||
正在补问时,补问书签优先于已报价调价,避免第 3 次反问出不了转人工卡。
|
||||
A 已判成调价且当前不是补问:交给当前已报价工单,避免旧海运书签抢走。
|
||||
图片识图在 Worker 写下的补问书签,HTTP 必须从 Redis 读到,否则「托盘」会变成再问运输方式。
|
||||
"""
|
||||
from agent.schema.land_options import looks_like_confirm
|
||||
from agent.policy.quote_adjust_ops import quoted_adjust_flow
|
||||
from agent.policy.handoff_human import is_handoff_frozen
|
||||
|
||||
land = get_land_text_flow()
|
||||
if looks_like_confirm(text):
|
||||
@@ -51,21 +80,22 @@ def _pick_text_flow(*, sender_id: str, text: str, injected_mode: str = "", prefe
|
||||
retry = land.restore_tms_retry_session(sender_id)
|
||||
if retry:
|
||||
return land
|
||||
if prefer_quoted:
|
||||
quoted = quoted_adjust_flow(sender_id)
|
||||
if quoted is not None:
|
||||
return quoted
|
||||
sea = get_sea_text_flow()
|
||||
air = get_air_text_flow()
|
||||
sea_sess = sea.session_of(sender_id)
|
||||
land_sess = land.session_of(sender_id)
|
||||
air_sess = air.session_of(sender_id)
|
||||
# 补问/核对手稿优先于「已报价调价」,避免第 3 次反问被调价路由冲掉、出不了转人工卡。
|
||||
for sess, flow in ((land_sess, land), (air_sess, air), (sea_sess, sea)):
|
||||
if _front_bookmark(sess):
|
||||
return flow
|
||||
if sea_sess and (sea_sess.business_line or "").upper() == "SEA":
|
||||
if prefer_quoted:
|
||||
quoted = quoted_adjust_flow(sender_id)
|
||||
if quoted is not None:
|
||||
return quoted
|
||||
if sea_sess and not is_handoff_frozen(sea_sess) and (sea_sess.business_line or "").upper() == "SEA":
|
||||
return sea
|
||||
if land_sess and (land_sess.business_line or "").upper() == "LAND":
|
||||
if land_sess and not is_handoff_frozen(land_sess) and (land_sess.business_line or "").upper() == "LAND":
|
||||
return land
|
||||
mode = (injected_mode or detect_transport_mode(text) or "").upper()
|
||||
if mode == "SEA":
|
||||
@@ -140,6 +170,7 @@ def handle_text_inquiry(
|
||||
flow=None,
|
||||
store=None,
|
||||
prefer_quoted: bool = False,
|
||||
prefer_handoff: bool = False,
|
||||
) -> str:
|
||||
"""
|
||||
处理一条私聊文字询价。
|
||||
@@ -177,6 +208,15 @@ def handle_text_inquiry(
|
||||
logger.info("text_inquiry 出站 ok=%s info=%s phase_reply=%s", ok, info, body[:80])
|
||||
return info if ok else ""
|
||||
|
||||
if prefer_handoff:
|
||||
phase = engine.offer_handoff(
|
||||
sender_id=message.sender_id,
|
||||
text=message.content or "",
|
||||
reply=reply,
|
||||
)
|
||||
logger.info("text_inquiry handoff phase=%s sender=%s", phase, message.sender_id)
|
||||
return phase
|
||||
|
||||
phase = engine.on_text(
|
||||
sender_id=message.sender_id,
|
||||
text=message.content or "",
|
||||
@@ -194,21 +234,26 @@ def handle_text_inquiry(
|
||||
|
||||
def handle_text_other(message: InboundMessage, *, store=None) -> str:
|
||||
"""
|
||||
闲聊/其它:若有待点按钮则当按钮;否则回首次单聊话术。
|
||||
闲聊/其它:补问短答续填;待点按钮当按钮;否则回首次单聊话术。
|
||||
"""
|
||||
from agent.policy import inquiry_copy as copy
|
||||
|
||||
if not message.has_sender():
|
||||
return "reject_no_sender"
|
||||
msg_store = store or get_message_store()
|
||||
if should_resume_other_as_inquiry(message):
|
||||
logger.info(
|
||||
"text_other 续填当前询价 sender=%s chars=%s",
|
||||
message.sender_id,
|
||||
len((message.content or "").strip()),
|
||||
)
|
||||
return handle_text_inquiry(message, store=msg_store)
|
||||
engine = _pick_text_flow(
|
||||
sender_id=message.sender_id, text=message.content or ""
|
||||
)
|
||||
sess = engine.session_for_action(
|
||||
message.sender_id, message.raw, text=message.content or ""
|
||||
)
|
||||
if sess and sess.phase == "wait_lost_reason":
|
||||
return handle_text_inquiry(message, store=msg_store)
|
||||
btn = engine.match_button(message.content or "", sess)
|
||||
if btn:
|
||||
return handle_text_inquiry(message, store=msg_store)
|
||||
|
||||
Reference in New Issue
Block a user