feat: 读标补齐五类清单与项目基本信息,修复国动样本暴露的 4 个问题
- 文字层 v2:页眉页脚带单独成句;写到页尾的句子和下一页首句接续(出处两页各一条) - 结构识别(最小版):十进制编号、冒号引出的列表找上级条款;上级条款写明无效的,条目照样认定 - 抽取:资格、评分、日期与递交、技术参数、项目基本信息各一份提示词;实质性条款出 v2 (认上级条款、补「做无效响应处理」等写法);各类取值核对;按首句合并; 拆开被合成一条的列举条款;描述标注方式的句子和表头碎片不当条款;* 号标注 - 项目:解析出的名称、编号、采购人、预算、截止时间、分包写回项目,用户改过的不覆盖 - 前端:清单项显示分值、参数要求、日期、证明材料 - 测试 40 个,新增两页虚构样例 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,8 @@ from bid_doctor.core.authz import Permission, require
|
||||
from bid_doctor.core.db import TenantContext
|
||||
from bid_doctor.core.errors import AppError
|
||||
from bid_doctor.core.ids import uuid7
|
||||
from bid_doctor.project.models import Lot, Project, ProjectMember
|
||||
from bid_doctor.document import citations
|
||||
from bid_doctor.project.models import Lot, Project, ProjectField, ProjectMember
|
||||
|
||||
UNNAMED = "未命名项目"
|
||||
|
||||
@@ -83,3 +84,46 @@ async def list_projects(s: AsyncSession, ctx: TenantContext, limit: int) -> list
|
||||
).tuples():
|
||||
lots.setdefault(pid, []).append(lot_no)
|
||||
return [(p, lots.get(p.id, [])) for p in projects]
|
||||
|
||||
|
||||
FIELD_ORDER = (
|
||||
"name",
|
||||
"code",
|
||||
"purchaser",
|
||||
"agency",
|
||||
"procurement_method",
|
||||
"legal_regime",
|
||||
"budget_total",
|
||||
"ceiling_total",
|
||||
"eval_method",
|
||||
"accept_consortium",
|
||||
"accept_imported",
|
||||
"sme_only",
|
||||
"deadline_at",
|
||||
)
|
||||
|
||||
|
||||
async def fields(s: AsyncSession, project_id: UUID) -> list[dict[str, Any]]:
|
||||
"""项目基本信息字段(FR-M2-03):当前值、来源(AI / 人工)、AI 原值、出处、补遗带来的待确认值。"""
|
||||
rows = (await s.execute(select(ProjectField).where(ProjectField.project_id == project_id))).scalars().all()
|
||||
cites = await citations.to_api_many(s, [c for r in rows for c in (r.ai_citation_id, r.pending_citation_id) if c])
|
||||
out = []
|
||||
for r in sorted(rows, key=lambda r: FIELD_ORDER.index(r.field_key)):
|
||||
human = r.human_value is not None
|
||||
out.append(
|
||||
{
|
||||
"key": r.field_key,
|
||||
"value": r.human_value if human else r.ai_value,
|
||||
"source": "human" if human else "ai" if r.ai_value is not None else "none",
|
||||
"ai_value": r.ai_value,
|
||||
"citation": cites.get(r.ai_citation_id) if r.ai_citation_id else None,
|
||||
"updated_by": None,
|
||||
"pending": {
|
||||
"value": r.pending_value,
|
||||
"citation": cites.get(r.pending_citation_id) if r.pending_citation_id else None,
|
||||
}
|
||||
if r.pending_value is not None
|
||||
else None,
|
||||
}
|
||||
)
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user