陆运补问把货物品名放进选项清单,并按销售原文回显已填项。
空着的运输分类不再被菜单第一项认成已填。空运报价改为货物信息加价格方案,锁舱成功回执补起运地、目的地、航司和航班日期。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,7 +20,10 @@ from agent.schema.field_validate import (
|
||||
)
|
||||
from agent.llm.extract_text import parse_labeled_facts
|
||||
from agent.schema.land_options import (
|
||||
drop_blank_paste_options,
|
||||
drop_land_prompt_echo,
|
||||
harvest_land_options,
|
||||
land_cargo_name,
|
||||
option_prompt,
|
||||
scrub_land_placeholder_ports,
|
||||
validate_land_options,
|
||||
@@ -220,15 +223,26 @@ def _segment_required_check(seg: Segment) -> tuple[dict[str, Any], dict[str, str
|
||||
)
|
||||
)
|
||||
option_missing = [str(x) for x in (opt.get("missing") or []) if str(x).strip()]
|
||||
cargo_missing = [str(x) for x in (check.get("missing") or []) if str(x).strip()]
|
||||
missing = option_missing + [k for k in cargo_missing if k not in option_missing]
|
||||
cargo_missing = [
|
||||
str(x)
|
||||
for x in (check.get("missing") or [])
|
||||
if str(x).strip() and str(x) not in option_missing and str(x) != "品名"
|
||||
]
|
||||
# 货物品名没填时仍算这张选项清单没完成,不进始发站待填。
|
||||
cargo_name = land_cargo_name(facts)
|
||||
missing = list(option_missing) + cargo_missing
|
||||
if not cargo_name:
|
||||
missing.append("品名")
|
||||
merged = dict(check.get("facts") or facts)
|
||||
merged.update({k: facts[k] for k in ("运输类型", "线路类别", "运输分类") if facts.get(k)})
|
||||
for key, val in facts.items():
|
||||
if str(key).startswith("_land_show_") and str(val).strip():
|
||||
merged[str(key)] = str(val).strip()
|
||||
check["facts"] = merged
|
||||
check["missing"] = missing
|
||||
check["ok"] = not missing
|
||||
check["need_land_subtype"] = False
|
||||
check["need_land_options"] = bool(option_missing)
|
||||
check["need_land_options"] = bool(option_missing) or not cargo_name
|
||||
return check, merged
|
||||
check = validate_required_fields(facts=dict(seg.facts), business_line=seg.mode)
|
||||
facts = dict(seg.facts)
|
||||
@@ -342,7 +356,10 @@ def _overlay_segments(
|
||||
continue
|
||||
blob = (neu.source or "").strip()
|
||||
if target.mode == "LAND":
|
||||
overlay = harvest_land_options(blob, dict(neu.facts))
|
||||
overlay = drop_blank_paste_options(
|
||||
harvest_land_options(blob, dict(neu.facts)),
|
||||
blob,
|
||||
)
|
||||
elif target.mode == "SEA":
|
||||
overlay = harvest_sea_class(blob, dict(neu.facts))
|
||||
else:
|
||||
@@ -412,16 +429,23 @@ def group_brief(
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def segments_to_payload(segments: list[Segment]) -> list[dict[str, Any]]:
|
||||
"""书签和工单里保存的段。只保留字符串,避免书签序列化掉类型。"""
|
||||
return [
|
||||
{
|
||||
"index": seg.index,
|
||||
"mode": seg.mode,
|
||||
"facts": {str(k): str(v) for k, v in (seg.facts or {}).items() if str(v).strip()},
|
||||
}
|
||||
for seg in segments
|
||||
]
|
||||
def segments_to_payload(
|
||||
segments: list[Segment],
|
||||
*,
|
||||
keep_prompt_echo: bool = True,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""
|
||||
书签和工单里保存的段。只保留字符串,避免书签序列化掉类型。
|
||||
|
||||
建单时 keep_prompt_echo=False,回显用的内部键不进工单。
|
||||
"""
|
||||
rows: list[dict[str, Any]] = []
|
||||
for seg in segments:
|
||||
facts = {str(k): str(v) for k, v in (seg.facts or {}).items() if str(v).strip()}
|
||||
if not keep_prompt_echo:
|
||||
facts = drop_land_prompt_echo(facts)
|
||||
rows.append({"index": seg.index, "mode": seg.mode, "facts": facts})
|
||||
return rows
|
||||
|
||||
|
||||
def segments_from_payload(raw: Any) -> list[Segment]:
|
||||
@@ -462,16 +486,13 @@ def _segment_clarify(seg: Segment, check: dict[str, Any]) -> str:
|
||||
if check.get("ok") and not check.get("need_land_subtype"):
|
||||
return ""
|
||||
missing = [str(x) for x in (check.get("missing") or []) if str(x).strip()]
|
||||
if check.get("need_land_subtype"):
|
||||
return (
|
||||
copy.CLARIFY_PASTE_HINT
|
||||
+ "\n1.运输类型(必填):\n(如:国内运输拼车)"
|
||||
)
|
||||
if seg.mode == "LAND" and (
|
||||
check.get("need_land_subtype") or check.get("need_land_options")
|
||||
):
|
||||
# 和单聊同一张清单:类型、线路、分类、货物品名。已填的留在复制框上面。
|
||||
return option_prompt(current=seg.facts)
|
||||
if seg.mode == "LAND":
|
||||
if check.get("need_land_options"):
|
||||
# 和单聊一样先列出线路类别、运输分类,选完再问询价字段。
|
||||
return option_prompt(current=seg.facts)
|
||||
cargo_missing = [k for k in missing if k not in _LAND_OPTION_KEYS]
|
||||
cargo_missing = [k for k in missing if k not in _LAND_OPTION_KEYS and k != "品名"]
|
||||
raw = copy.ask_land_fields(
|
||||
facts=seg.facts,
|
||||
missing_keys=cargo_missing,
|
||||
@@ -594,7 +615,7 @@ def _facts_from_body(body: str, mode: str) -> dict[str, str]:
|
||||
if val and not str(facts.get(key) or "").strip():
|
||||
facts[key] = val
|
||||
if mode == "LAND":
|
||||
facts = harvest_land_options(body, facts)
|
||||
facts = drop_blank_paste_options(harvest_land_options(body, facts), body)
|
||||
if mode == "SEA":
|
||||
facts = harvest_sea_class(body, facts)
|
||||
return facts
|
||||
@@ -624,7 +645,7 @@ def _split_by_segment_mark(text: str) -> dict[int, dict[str, str]]:
|
||||
end = marks[i + 1].start() if i + 1 < len(marks) else len(raw)
|
||||
body = raw[mark.end() : end]
|
||||
facts = parse_labeled_facts(body)
|
||||
facts = harvest_land_options(body, facts)
|
||||
facts = drop_blank_paste_options(harvest_land_options(body, facts), body)
|
||||
facts = harvest_sea_class(body, facts)
|
||||
facts = harvest_oral_measures(body, facts)
|
||||
if facts:
|
||||
|
||||
Reference in New Issue
Block a user