feat(server): 参考 BidEngine 补五项:原因码、截断重跑、项目信息逐项表态、占位符、提示词规则对应校验
- 待确认记原因码(extract.FAILURES,存在 ai_values.failures),解析结果按原因计数 (verify_failures);前端待确认条目显示具体原因 - 相邻分块重叠约 800 字;模型输出被截断或不是合法 JSON 时对半重跑(最多 3 层), 拆到底仍不完整记 output_incomplete。修复:以前截断时整块条目被当成「没有结果」悄悄丢掉 - 项目基本信息提示词 v2:12 个字段逐项表态 found / ambiguous / not_found,跨分块合并为 found / absent / needs_review(info_fields) - 「____元」「××」「( )」「待填」等占位符不算取值 - 提示词 substantive v4,qualification / scoring / schedule / tech_param v3:每条禁止事项 对应一个原因码,对照表在 prompts/README.md - 顾问(Fable)深读参考项目的结论补进 ref-bid-engine-analysis.md §5;架构 §13 SK12 - 待确认:国动 4 → 2,S02 13 → 3,S06 57 → 55 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -109,7 +109,7 @@ async def _stage(ctx: TenantContext, job_id: UUID, stage: str) -> dict[str, Any]
|
||||
return checkpoints
|
||||
|
||||
|
||||
async def _stages(ctx: TenantContext, job_id: UUID) -> dict[str, int]:
|
||||
async def _stages(ctx: TenantContext, job_id: UUID) -> dict[str, Any]:
|
||||
async with tenant_tx(ctx) as s:
|
||||
job = (await s.execute(select(ParseJob).where(ParseJob.id == job_id))).scalar_one()
|
||||
doc = (await s.execute(select(SourceDocument).where(SourceDocument.id == job.document_id))).scalar_one()
|
||||
@@ -189,7 +189,7 @@ async def _stages(ctx: TenantContext, job_id: UUID) -> dict[str, int]:
|
||||
last[0] = pct
|
||||
await _progress(ctx, job_id, "extract", pct)
|
||||
|
||||
items, info = await extract.run(ctx, job_id, doc_info, progress)
|
||||
items, info, run_stats = await extract.run(ctx, job_id, doc_info, progress)
|
||||
|
||||
await _stage(ctx, job_id, "verify") # 三道校验在抽取时逐条做完;这里只是进度节点
|
||||
await _stage(ctx, job_id, "merge")
|
||||
@@ -197,7 +197,15 @@ async def _stages(ctx: TenantContext, job_id: UUID) -> dict[str, int]:
|
||||
d = (await s.execute(select(SourceDocument).where(SourceDocument.id == doc.id))).scalar_one()
|
||||
lots = await project_extracted.apply(s, ctx, d, info, extract.legal_regime_by_rule(body), items)
|
||||
stats = await checklist.merge(s, ctx, d, job_id, items, notes, lots)
|
||||
return {**stats, "lots_found": len([k for k in lots if k != "默认"])}
|
||||
return {
|
||||
**stats,
|
||||
"lots_found": len([k for k in lots if k != "默认"]),
|
||||
# 质量统计(评测和排查用):没通过校验的原因码条数、对半重跑次数、拆到底仍不完整的分块、项目信息各字段的结论
|
||||
"verify_failures": {k.removeprefix("fail:"): n for k, n in run_stats.items() if k.startswith("fail:")},
|
||||
"chunks_split": run_stats.get("chunks_split", 0),
|
||||
"output_incomplete": run_stats.get("output_incomplete", 0),
|
||||
"info_fields": {k: v["status"] for k, v in info.status.items()},
|
||||
}
|
||||
|
||||
|
||||
async def _finish(
|
||||
@@ -206,7 +214,7 @@ async def _finish(
|
||||
status: str,
|
||||
error_class: str | None,
|
||||
code: str | None,
|
||||
result: dict[str, int] | None = None,
|
||||
result: dict[str, Any] | None = None,
|
||||
) -> None:
|
||||
async with tenant_tx(ctx) as s:
|
||||
job = (await s.execute(select(ParseJob).where(ParseJob.id == job_id))).scalar_one()
|
||||
|
||||
Reference in New Issue
Block a user