落地多段联运私聊:齐了才建单拉群,附件只收格子值,核对改正不再整单重开。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 15:08:15 +08:00
co-authored by Cursor
parent 6e3e09a316
commit 2334524bb8
30 changed files with 4033 additions and 40 deletions
@@ -30,6 +30,30 @@ VisionFn = Callable[..., dict[str, Any]]
DownloadFn = Callable[[str], tuple[bytes, str]]
PutFn = Callable[..., dict[str, Any]]
def prefer_extracted_oral(raw_text: str, organized: str) -> str:
"""
千问把报价单整理成空、几个字或几十个字时,改用抽出的单元格原文。
测服复现:陆运 997 字被压成 48 字、海运 1325 字被压成 52 字,
多段补问就只剩货量/运输分类,起运港目的港整段待补充。
整理结果够长、没有被大幅压短时仍用整理后的,方便人读。
"""
raw = (raw_text or "").strip()
org = (organized or "").strip()
if not raw:
return org
if not org:
return raw
# 报价单原文很长、整理后只剩几分之一:用原文。997→48、1325→52 都走这里。
if len(raw) >= 200 and len(org) * 8 < len(raw):
return raw
if len(org) < 8 and len(raw) >= 40:
return raw
if len(org) < 40 and len(org) * 5 < len(raw):
return raw
return org
_STASH: dict[str, bytes] = {}
_STASH_LOCK = threading.Lock()
_PRECEDE_NOISE = (
@@ -68,10 +92,17 @@ def _stash_get(key: str) -> bytes:
def drop_all_private_bookmarks(sender_id: str) -> None:
"""三线当前书签都丢掉;已出号仍能按工单号找回。"""
"""
海运/空运/陆运/多段当前书签都丢掉;已出号仍能按工单号找回。
附件发卡或认完必须连多段一起清:否则旧补问草稿会把新附件口播当成补字段,
海运只剩货量/运输分类,陆运再问一遍运输类型。
"""
from agent.handlers.image_inquiry import drop_all_private_bookmarks as _drop
from agent.policy.multi_text_flow import get_multi_text_flow
_drop(sender_id)
get_multi_text_flow().drop_current_bookmark(sender_id)
def is_active_attachment_wait(sender_id: str, *, now: Optional[float] = None) -> bool:
@@ -404,6 +435,8 @@ def finish_attach_wave(
media=dict(seed_message.media) if seed_message else {},
raw=dict(seed_message.raw) if seed_message else {},
)
# 认完附件一律新开:不能粘在发卡前留下的多段/单段补问草稿上。
drop_all_private_bookmarks(sender_id)
phase = handle_text_inquiry(inbound, store=_StoreProxy())
if reason and not prefix_used["v"]:
msg_store.enqueue_outbound(
@@ -612,9 +645,18 @@ def _recognize_file(
allow_network=bool(settings.llm_allow_network and settings.llm_data_usage_confirmed),
)
if packed.get("ok") and str(packed.get("text") or "").strip():
organized = str(packed.get("text") or "")
organized = prefer_extracted_oral(raw_text, str(packed.get("text") or ""))
elif not packed.get("ok"):
org_err = str(packed.get("error") or org_err or "attachment_text_failed")
logger.info(
"attachment 认完 sender=%s idx=%s name=%s raw_len=%s oral_len=%s err=%s",
sender_id,
index,
filename,
len(raw_text),
len((organized or "").strip()),
org_err or "-",
)
book.complete_material(
sender_id,
index,