账号支持只看本账号看板;模板重新解析改为保留原映射并多轮补缺。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-09-19 10:38:53 +08:00
co-authored by Cursor
parent 6cd6803147
commit 9bb69ae72e
19 changed files with 807 additions and 114 deletions
+34 -9
View File
@@ -111,28 +111,50 @@ def process_recognition(data: dict[str, Any], *, allow_network: bool = True) ->
def _process_quote_template_parse(payload: dict[str, Any], *, allow_network: bool) -> dict[str, Any]:
"""跑 sheet_map 并回写主账;失败也必须回写 failed+原因。"""
"""
跑 sheet_map 并回写主账;失败也必须回写 failed+原因。
mergeExisting=true(未换文件重新解析)时:与 existingMapping 补缺合并后再回写,
旧字段优先保留;换文件/首传不传该标记,整份覆盖。
"""
from agent.config import get_settings
from agent.llm.mode_sheet_map import invoke_sheet_map
from agent.llm.mode_sheet_map import (
assess_mapping_gaps,
invoke_sheet_map,
merge_mapping_prefer_existing,
)
version_id = str(payload.get("versionId") or "").strip()
settings = get_settings()
net = bool(allow_network and settings.llm_allow_network)
result = invoke_sheet_map(payload, allow_network=net)
result = invoke_sheet_map(payload, allow_network=net, timeout_seconds=240.0, max_rounds=3)
merge_existing = bool(payload.get("mergeExisting") or payload.get("merge_existing"))
existing = payload.get("existingMapping") or payload.get("existing_mapping")
body: dict[str, Any]
if result.get("ok") and isinstance(result.get("mapping"), dict):
mapping = dict(result["mapping"])
gaps = result.get("gaps_after")
if not isinstance(gaps, list):
gaps = mapping.get("mappingGaps") if isinstance(mapping.get("mappingGaps"), list) else []
mapping["mappingGaps"] = [str(g) for g in gaps if g]
if merge_existing and isinstance(existing, dict):
mapping = merge_mapping_prefer_existing(existing, mapping)
# 合并后再对照清单复评缺口,避免角标沿用合并前数字
remaining = assess_mapping_gaps(payload, mapping)
mapping["mappingGaps"] = [str(g) for g in remaining if g]
if not remaining:
mapping["unmappedRequired"] = []
mapping["unmappedLabels"] = []
else:
gaps = result.get("gaps_after")
if not isinstance(gaps, list):
gaps = mapping.get("mappingGaps") if isinstance(mapping.get("mappingGaps"), list) else []
mapping["mappingGaps"] = [str(g) for g in gaps if g]
# 运营可读摘要:点数之外固定带上未解析项
n_fields = len(mapping.get("fields") or {})
n_fee = len(mapping.get("feeRegions") or []) if isinstance(mapping.get("feeRegions"), list) else 0
n_route = len(mapping.get("routeRegions") or []) if isinstance(mapping.get("routeRegions"), list) else 0
points = n_fields + n_fee + n_route
parse_message = f"已解析 {points} 个映射点"
if mapping["mappingGaps"]:
if merge_existing:
parse_message += "(保留原映射并补缺)"
if mapping.get("mappingGaps"):
preview = ";".join(mapping["mappingGaps"][:8])
more = len(mapping["mappingGaps"]) - 8
parse_message += f";未解析到 {len(mapping['mappingGaps'])} 项:{preview}"
@@ -144,6 +166,7 @@ def _process_quote_template_parse(payload: dict[str, Any], *, allow_network: boo
"mappingJson": mapping,
"parseStatus": "parsed",
"parseMessage": parse_message,
"mergeExisting": merge_existing,
}
else:
err = str(result.get("error") or "AI 解析失败")
@@ -152,12 +175,14 @@ def _process_quote_template_parse(payload: dict[str, Any], *, allow_network: boo
"ok": False,
"parseStatus": "failed",
"parseMessage": err,
"mergeExisting": merge_existing,
}
posted = _post_parse_result(body)
logger.info(
"quote_template_parse done versionId=%s ok=%s posted=%s",
"quote_template_parse done versionId=%s ok=%s merge=%s posted=%s",
version_id,
body.get("ok"),
merge_existing,
posted.get("ok"),
)
return {"ok": bool(body.get("ok")), "posted": posted, "kind": "quote_template_parse"}