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:
@@ -23,6 +23,7 @@ from typing import Any
|
||||
from uuid import UUID
|
||||
|
||||
from bid_doctor.ai import prompts
|
||||
from bid_doctor.ai import service as ai_service
|
||||
from bid_doctor.ai.service import provider
|
||||
from bid_doctor.checklist import extract
|
||||
from bid_doctor.core.db import TenantContext
|
||||
@@ -72,9 +73,12 @@ async def cached_run_json(ctx: Any, *, job_type: str, job_id: Any, task: str, pr
|
||||
raise
|
||||
print("retry", task, e, file=sys.stderr)
|
||||
await asyncio.sleep(3)
|
||||
data = {"data": r.data, "model": r.model, "tokens_in": r.tokens_in, "tokens_out": r.tokens_out}
|
||||
data = {"data": r.data, "model": r.model, "tokens_in": r.tokens_in, "tokens_out": r.tokens_out,
|
||||
"incomplete": r.incomplete}
|
||||
f.write_text(json.dumps(data, ensure_ascii=False))
|
||||
calls.append({"task": task, "version": version, "user": user, **data})
|
||||
if data.get("incomplete"):
|
||||
raise ai_service.OutputIncomplete(task) # 和线上一样:输出被截断时由 extract.run 对半重跑
|
||||
return data["data"]
|
||||
|
||||
|
||||
@@ -97,7 +101,7 @@ async def main() -> None:
|
||||
declared={m for n in notes for m in n.markers},
|
||||
)
|
||||
ctx = TenantContext(tenant_id=UUID(int=1), user_id=UUID(int=1))
|
||||
items, info = await extract.run(ctx, UUID(int=2), doc)
|
||||
items, info, run_stats = await extract.run(ctx, UUID(int=2), doc)
|
||||
|
||||
by_sid = {f"p{s.page_no}s{s.seq}": s for s in body}
|
||||
# ---------- 结果 ----------
|
||||
@@ -190,6 +194,9 @@ async def main() -> None:
|
||||
f"条目 {len(items)}:" + ",".join(f"{z}/{r or '-'} {n}" for (z, r), n in zone.most_common()),
|
||||
"按类别:" + ",".join(f"{c}/{z}:{n}" for (c, z), n in sorted(cats.items())),
|
||||
"项目信息:" + ",".join(f"{k}={getattr(v, 'value', v)}" for k, v in info.fields.items())[:600],
|
||||
"项目信息结论:" + ",".join(f"{k}:{v['status']}{v.get('codes') or ''}" for k, v in info.status.items()),
|
||||
"对半重跑 {} 次,拆到底仍不完整 {} 块".format(run_stats.get("chunks_split", 0), run_stats.get("output_incomplete", 0)),
|
||||
"没通过校验的原因:" + ",".join(f"{k.removeprefix('fail:')} {n}" for k, n in sorted(run_stats.items()) if k.startswith("fail:")),
|
||||
"",
|
||||
"## 模型输出审计",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user