更名说明:本项目曾用名「ScrapeFlow」,因名称重名冲突,正式更名为「标小智」(BidAgent)。仓库 git 历史与部分早期文档中残留的「ScrapeFlow」字样为更名前遗留,不影响当前项目。
技术定位:本项目的核心是「可验证文档抽取」——LLM 只生成候选,确定性程序验证,每个结果可回溯原文。该技术通用,可迁移到科研文献调研、实验数据提取等场景;招投标数据是它的首个落地验证场景。
面向供应链金融贷前尽调的可验证招投标数据引擎 · GOAI 2026。单篇公告核验成本不足 1 分钱、端到端约 24 秒(620 篇金标实测),把供应商中标记录核验从人工约 1-2 人时压缩到分钟级——且每个数字都可回溯公告原文:LLM 只生成候选,确定性程序负责验证。
当前状态:v4.1 对齐版(GOAI 世界人工智能开源大赛 · 无界应用赛道 · AI+金融方向) 测试:2435 passed · 评测数据:829 篇真实公告 · 金标 620 篇 · 数据源:10+ 个省级平台 · 分支:feature/qoder-sprint-realtime-quality(复赛)
| 想看什么 | 去哪里 |
|---|---|
| 一键跑起来 | python run_demo.py——已预置 829 条真实公告 / 143 家组织画像 / 586 条证据,启动即见活系统;浏览存量数据无需任何 LLM key(仅新公告采集需配置) |
| 演示页面 | 启动后访问 http://localhost:8000/ui:工作台 / 智能查询 / 组织画像 / 质量看板 |
| 3 分钟 Demo 视频 | 包内 标小智_Demo视频.webm(附字幕 标小智_Demo字幕.srt) |
| 路演 PPT | 包内 标小智_初赛路演_v2.pptx |
| 项目简介 | 包内 introduction_500.md(419 字,8 要素) |
| 关键数字 | 2435 测试通过 · 覆盖率 88.85% · 金标 620 篇 · 单篇核验成本 <1 分钱 · 10+ 省级数据源 |
- 一句话定位:面向供应链金融贷前尽调与企业采购核验的可验证招投标数据引擎——将不可核验的 LLM 输出转化为可复核、可追踪的数据资产
- 核心用户:供应链金融贷前尽调人员
- 系统定位:位于金融风控的数据准备与事实核验环节,为后续人工尽调或其他风控系统提供带证据的招投标数据,而非直接替代风控决策
- 核心差异化:LLM 只生成字段和证据候选,确定性程序负责在原文快照中搜索验证,找不到依据的字段一律标记为无依据不输出
- 每个字段可绑定多段原文证据,区分主证据、限定条件和推导输入
- LLM 只生成字段和证据候选,确定性程序负责验证
- 区分项目、公告、来源页面和页面版本四层实体
- 区分官方原始发布、官方转载、商业转载和索引页面
- 识别同源转载,避免将转载数量误判为独立交叉验证
- 将抽取支持度、来源质量和交叉验证状态独立保存
- 使用独立金标测试集验证准确率、覆盖率和无依据输出率
- 只输出可解释的公开招投标活动观察信号,不输出信用评分
TenderProject(采购项目)
└── TenderNotice(业务公告)
├── NoticeParticipant(公告参与关系)
└── NoticeSource(来源页面)
└── NoticeVersion(抓取版本)
└── ExtractedField(抽取字段)
└── FieldEvidenceLink
└── Evidence(字段证据)
辅助实体:Organization(组织机构)、NoticeParticipant(参与关系)、ProjectIdentifier(项目标识)、FactAssertionKey(事实断言键)。所有核心实体使用无业务含义的内部稳定主键(ULID)。
意图解析 → 采集执行 → 数据加工 → 质量保障 → 金融分析 → 报告交付
- LLM 只生成字段和证据候选,确定性程序负责验证
- 5 级降级匹配:L1 精确 → L2 空白归一化 → L3 全半角统一 → L4 金额日期格式变体 → L5 模糊匹配/失败标记
- 双坐标映射(normalized_index ↔ raw_index),证据偏移量在快照中可稳定复现,前端不依赖实时网页 DOM
- 找不到依据的字段一律标记为无依据不输出
- 来源角色判定:official_original / official_repost / commercial_repost / unknown
- 同源转载识别(SimHash 汉明距离 ≤ 3),避免将转载数量误判为独立交叉验证
- 事实断言键(FactAssertionKey):跨源比较前确保双方表达同一业务事实
- 页面版本追踪,历史版本不被新版本覆盖
- 10+ 个省级官方来源统一接入 SourceAdapter 实时层(ccgp 中央 + ggzy 全国 + 粤/苏/滇/鲁/津/青岛/豫/浙/粤)
- 省级批量组网:按域名分桶调度,域名级 8 秒频率限制 + 403 即停不重试
- 实时交叉验证:多源佐证链 900↔927 条跨源对应,库内 829 条十源公告
- 实时采集面板:Web Demo 内可视化采集进度、来源状态和交叉验证结果
- 入库即存:每条证据入库时计算 SHA-256 哈希,801/801 全量存证
- 重放核验:篡改可检出,重放命令一键验证证据完整性
- 生命周期链:采集→抽取→验证→存储 每环节哈希串联,可追溯
- 尽调单证据链存证版:金融尽调单的每条证据可独立核验来源
- 中标应收账款放款前核验:复用 verify_award 内核 + 无编号反查
- 超额融资 CRITICAL 预警:中标金额 vs 融资金额比对,超额自动标记
- 一页尽调单 API 端点:输出结构化尽调报告,每个数字带证据回溯
- 三级分类(high / review / low):基于抽取支持度 + 来源质量 + 交叉验证状态
- 四种输出策略:strict / default / loose / audit
| 信号 | 说明 |
|---|---|
| 中标活跃度 | 近 90 天公开中标次数和金额趋势,不作正负定性 |
| 公开中标集中度 | 当前覆盖数据中 Top 3 采购人及地区占比 |
| 废标公告关联 | 企业在废标或流标公告中被观察到的次数,不直接归因 |
| 明确投标否决 | 公告明确写明企业投标被否决,并记录原因 |
| 信息冲突观察 | 相同事实断言在不同有效来源中出现矛盾 |
| 高频共现提示(选做) | 企业与其他企业在同一标段被反复观察到,不用于判断围标 |
严谨表述(v4.1 §9.3):使用「公开公告中观察到的投标出现次数」,不得使用「企业实际投标次数」;高频共现必须附带说明「仅凭共现不能判断企业关联关系或围标行为」。
- 域名级频率限制(DomainRateLimiter):默认 8 秒间隔,按域名独立计数,失败时回滚 reservation
- robots.txt 合规检查(RobotsChecker):30 分钟域名级缓存,不可达时默认允许
- 来源白名单(SourceWhitelist):维护允许采集的来源平台/域名清单,支持运行时下架/重新启用,集成到 scraper 前置检查
- 数据删除(DataDeletionService):支持按来源 URL、来源平台、公告来源实例、页面快照、用户授权数据 5 种范围删除,记录审计日志
- 失败回退:触发 403/封禁时停止访问,不进行规避
- API Key 使用高熵随机值,服务端只保存基于服务端密钥的 HMAC-SHA256 摘要(secrets.compare_digest 防时序攻击)
- 密码使用 Argon2id 哈希(防彩虹表/暴力破解)
- Cookie 使用 AES-GCM 加密(nonce 唯一)
- SSRF 防护:仅允许 HTTP/HTTPS,拦截内网/回环/链路本地/云元数据地址,重定向后重新检查
- 路径安全:白名单存储目录,禁止路径穿越,文件名与真实存储键分离
- 日志不得记录凭证
- 证据 recall / precision / IoU 三大指标(span 级口径:衡量证据文本边界与金标的重合度)
- 项目级 Bootstrap 95% 置信区间
- 四组消融实验(A/B/C/D),其中 evidence_precision 为字段级口径(输出字段的证据可在原文定位),与 span 级指标不同维度,不可直接比较
- v4.1 §10 新指标:null_false_positive_rate(金标 absent/not_applicable 字段零误报)
| 接口 | 方法 | 说明 |
|---|---|---|
| /api/projects/search | GET | 搜索采购项目 |
| /api/projects/{project_id} | GET | 获取项目及公告生命周期 |
| /api/notices/{notice_id} | GET | 获取公告详情 |
| /api/notices/{notice_id}/sources | GET | 获取来源页面和谱系 |
| /api/notices/{notice_id}/participants | GET | 获取公告参与方列表 |
| /api/sources/{source_id}/versions | GET | 获取页面版本历史 |
| /api/fields/{field_id} | GET | 获取字段和全部证据 |
| /api/organizations/search | GET | 搜索组织实体 |
| /api/organizations/{org_id} | GET | 获取组织实体公开活动画像 |
| /api/extract/tasks | POST | 提交异步抽取任务 |
| /api/extract/tasks/{task_id} | GET | 查询任务状态 |
| /api/stats/quality | GET | 获取数据质量和评测统计 |
抽取任务异步状态:queued / running / partially_succeeded / succeeded / failed
工作台 / 招标检索 / 公告列表 / 证据验证详情 / 组织画像 / 质量评测 / 版本历史 / 智能问答
- SMTP 邮件 + Webhook HMAC 签名,at-least-once 语义 + content_hash 幂等去重
- Word 报告自动生成 + cron 定时推送
| 项目 | 数值 |
|---|---|
| 数据库公告总数 | 829 篇(2026-08 多源实时采集灌库,SimHash 去重) |
| 金标集 | 620 篇(tests/fixtures/gold/gold_dataset_v4.json,document_id 双口径唯一,十源扩标) |
| W3 评测集 | 100 篇(ccgp_w3) |
| 数据源 | 10+ 个省级平台(ccgp 中央 + ggzy 全国 + 粤/苏/滇/鲁/津/青岛/豫/浙/粤) |
| 公告类型覆盖 | tender / award / correction / 其他 |
| 金标字段总数(620 篇全量) | 3720 |
| 指标 | A 组(Direct LLM) | B 组(LLM+候选证据) | C 组(LLM+程序验证) | D 组(完整 BidAgent) |
|---|---|---|---|---|
| unjustified_rate | 100.00% | 0.00%(失真) | 3.01% | 0.00% |
| field_precision | 96.17% | 87.76% | 87.59% | 98.08% |
| evidence_precision | N/A | N/A | 100.00% | 100.00% |
| 指标 | A 组 | B/C/D 组 | 目标 |
|---|---|---|---|
| null_false_positive_rate | 4.37% | 0.63% | <5%(达标) |
仅剩 1 个空值误报(w3_correction_043),经核对为金标标注矛盾。
| 指标 | A 组(Direct LLM) | B 组(LLM+候选证据) | C 组(LLM+程序验证) | D 组(完整 BidAgent) |
|---|---|---|---|---|
| field_precision | 88.04% | 96.16% | 96.13% | 97.60% |
| unjustified_rate | 100.00% | 0.00% | 4.05% | 0.00% |
| evidence_precision | N/A | N/A | 99.91% | 99.91% |
| null_false_positive_rate | 22.99% | 0.79% | 0.57% | 0.57% |
| multi_value_f1_avg | 0.7797 | 0.8537 | 0.8574 | 0.8574 |
口径说明:620 篇全覆盖(fields_total=3720,十源金标扩标),与 99 篇消融同一套 run_group/summarize 口径;D 组选择性输出拒绝低置信字段后 fields_evaluable=2246(不确定的不输出)。产物:_w3_outputs/gold598_retest.json,model_id=deepseek-v4-flash,temperature=0.0。
- 2435 passed · 0 errors / 0 failures(含 5 个 Playwright 页面级 E2E:
tests/test_e2e_pages.py,真实 uvicorn + chromium,覆盖工作台/列表/详情/看板/搜索渲染主路径与零 JS 异常) - 0 warnings(已清理 asyncio mark 误标与 datetime.utcnow() 弃用告警)
- 测试覆盖率 88.85%(pyproject.toml 阈值 40%,2435 用例全量实测)
- 10+ 个省级官方来源适配器(ccgp 中央 + ggzy 全国 + 粤/苏/滇/鲁/津/青岛/豫/浙/粤九省)
- 招标公告、中标公告和更正公告
- 六类核心结构化字段(项目编号、采购人名称、中标人名称、金额及金额类型、发布日期、投标截止日期)
- 字段级多证据验证
- 页面快照与版本管理
- 同源转载识别
- 三维质量评估(抽取支持度 / 来源质量 / 交叉验证状态)
- 独立金标评测(含消融实验)
- Web Demo + REST API
- 基础组织实体公开活动画像
- 证据 SHA-256 存证(入库即存哈希,篡改可检出,重放核验 801/801 通过)
- 金融尽调单(中标应收账款放款前核验 + 超额融资 CRITICAL 预警)
- 中标人覆盖率 31% → 81.1%(确定性解析器 + LLM 提议规则裁判)
- 多源实时采集面板(省级批量组网 + 实时交叉验证)
- 企业信用评分 / 授信建议 / 中标概率预测 / 围标自动判定
- 全品类 BOQ 异常检测
- 分布式采集 / 图数据库 / 多租户系统
- 商业平台账号池及验证码自动处理
- PDF/OCR 深度解析
历史代码中存在的 BOQ 异常检测与废标风险预警模块为早期实验性实现,v4.1 MVP 不包含这些能力,不作为对外功能宣传。
# 1. 克隆 + 进入目录
git clone <repo_url> BidAgent && cd BidAgent
# 2. 创建虚拟环境 + 安装依赖
python -m venv .venv
.venv\Scripts\activate # Windows
pip install -r requirements.txt
python -m playwright install chromium
# 3. 配置环境变量(生成密钥 + 填 LLM key)
cp .env.example .env
python -c "import secrets; print(secrets.token_hex(32))" # 填入 SECRET_KEY=
# 编辑 .env 设置 DEEPSEEK_API_KEY=sk-xxx(或其他 LLM provider)
# 4. 启动服务
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# 5. 打开 Web Demo
# http://localhost:8000/ui (工作台首页)
# http://localhost:8000/docs (API 文档)
# http://localhost:8000/health (健康检查)一键启动(含数据库初始化 + 样例加载):
python run_demo.py详见 examples/ 目录的示例输入输出。
- Python 3.11+
- Playwright Chromium 二进制
cd BidAgent
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
pip install -r requirements.txt
python -m playwright install chromiumcp .env.example .env生成必需密钥:
# SECRET_KEY: 64 字符 hex(必须用 token_hex(32) 生成)
python -c "import secrets; print(secrets.token_hex(32))"把生成结果填入 .env 的 SECRET_KEY=。同时设置至少 8 字符的 ADMIN_SECRET。
抽取与意图解析均走 OpenAI 兼容协议,通过 .env 切换供应商:
# 供应商:deepseek(默认)/ dashscope / zhipu / openai
LLM_PROVIDER=deepseek
# 各供应商各自的 key(只填所选 provider 的即可)
DEEPSEEK_API_KEY=sk-xxx
# DASHSCOPE_API_KEY=sk-xxx # 通义千问(阿里云百炼)
# ZHIPU_API_KEY=xxx # 智谱 GLM
# OPENAI_API_KEY=sk-xxx
# 可选覆盖
# LLM_EXTRACTION_MODEL=deepseek-reasoner # 抽取任务单独指定模型
# LLM_BASE_URL / LLM_API_KEY # 指向任意 OpenAI 兼容端点(如自建代理)
# LLM_JSON_MODE=true/false # 强制开关 json_object response_format说明:
- 未支持
response_format=json_object的模型(如部分 GLM 版本)会自动关闭该参数, 解析层用宽松 JSON 解析器兜底(去围栏 / 截取花括号 / 尾逗号修复),解析失败还会 追加纠正指令自动重试一次,抗偶发 JSON 破损。 - 切换模型后
prompt_hash不变(prompt 内容未变),model_id记录实际使用的模型, 评测报告可区分口径。
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000-
API 文档 (Swagger UI): http://localhost:8000/docs
-
Web Demo: http://localhost:8000/ui
供评委 / 审查者核查核心声明的 grep 命令:
# 1. 验证引擎是否真独立于 LLM(预期:零匹配)
grep -r "openai\|anthropic\|chat.completion\|AsyncOpenAI" app/processors/
# 2. 双坐标映射实现
grep -rn "OffsetMapping\|to_normalized\|to_raw" app/processors/evidence_locator/
# 3. 5 级降级匹配
grep -rn "_match_exact\|_match_stripped\|_match_no_punct\|_match_substring" app/processors/evidence_locator/
# 4. 403 即停不重试
grep -n "HttpForbiddenError\|403\|raise" app/core/scraper.py
# 5. 凭证安全(nonce 随机 + 防时序攻击 + Argon2id 参数)
grep -n "os.urandom\|compare_digest\|memory_cost\|time_cost" app/utils/credentials.py
# 6. SimHash 用 jieba 分词
grep -n "jieba\|_tokenize\|threshold" app/processors/simhash.py
# 7. ULID 主键 + 外键索引
grep -n "ulid\|ULID\|index=True\|ForeignKey" app/models/organization.py
# 8. 运行凭证安全测试(45 用例,分支 100%)
pytest tests/test_credentials.py -v# 依赖漏洞扫描(已验证:No known vulnerabilities found)
pip-audit --requirement requirements.txtdocker-compose up -d详见 DEPLOY.md。
pytest -v# 覆盖率
pytest --cov=app --cov-report=term-missing测试范围包含 v4.1 新增:test_rate_limiter / test_robots_checker / test_data_deletion / test_source_whitelist / test_repost_features / test_credentials / test_v41_api / test_v41_fields / test_demo_pages_smoke / test_real_demo_api 等。
| 数据源 | 类型 | 说明 |
|---|---|---|
| ccgp.gov.cn | 官方公开 | 中国政府采购网(中央,MVP 适配器) |
| ggzy.gov.cn | 官方公开 | 全国公共资源交易平台(MVP 适配器) |
| ccgp-hubei.gov.cn | 官方公开 | 湖北省政府采购网(实时适配器) |
| ccgp-jiangsu.gov.cn | 官方公开 | 江苏省政府采购网(实时适配器) |
| ccgp-yunnan.gov.cn | 官方公开 | 云南省政府采购网(实时适配器) |
| ccgp-shandong.gov.cn | 官方公开 | 山东省政府采购网(实时适配器) |
| ccgp-tianjin.gov.cn | 官方公开 | 天津市政府采购网(实时适配器) |
| ccgp-qingdao.gov.cn | 官方公开 | 青岛市政府采购网(实时适配器) |
| ccgp-henan.gov.cn | 官方公开 | 河南省政府采购网(实时适配器) |
| ccgp-zhejiang.gov.cn | 官方公开 | 浙江省政府采购网(实时适配器) |
| ccgp-guangdong.gov.cn | 官方公开 | 广东省政府采购网(实时适配器) |
采集行为:域名级 8 秒频率限制 + robots.txt 合规检查 + 来源白名单 + 403 不重试。不绕过登录墙、不抓取付费内容。
- 不采集个人隐私数据(身份证/手机号/家庭住址等)
- 联系人电话/邮箱使用 SHA256 hex 存储
- API Key 用 HMAC-SHA256 摘要,密码用 Argon2id,Cookie 用 AES-GCM
- 不输出供应商信用评分(v4.1 §9.1),所有信号仅供人工尽调参考
- 报告输出明确标注「AI 生成,仅供参考,决策请人工复核」
- 定位为数据服务商,不提供金融建议,不承担金融决策责任
- 不输出信用评分,不判断围标,不提供授信建议
详见 compliance.md。
| 文档 | 位置 | 说明 |
|---|---|---|
| v4.1 总规划 | docs/BidAgent_项目总体规划_v4.1_执行定稿版.md |
v4.1 执行定稿 |
| GOAI 提交材料 | GOAI_初赛提交材料_正式版.md |
初赛作品简介 + 技术指标 |
| 合规声明 | _w2_report/compliance.md |
数据来源 / 隐私保护 / AI 反幻觉 / 行业边界 |
| 部署文档 | DEPLOY.md |
Docker 部署说明 |
| W3 评测报告 | _w3_outputs/w3_ablation_smoke_v41_rerun_report.md |
v4.1 指标验证报告 |
| 99 篇全量消融 | _w3_outputs/w3_ablation_full_99.json |
4 组 A/B/C/D |
| Bootstrap CI | _w3_outputs/w3_bootstrap_ci_full_99.json |
99 篇置信区间 |
| 金标冻结 | tests/fixtures/gold/gold_frozen_v1.json |
金标标注冻结 |
| 金标合集(620 篇) | tests/fixtures/gold/gold_dataset_v4.json |
w4/w5/w6 十源扩标合并,document_id 唯一 |
| 验证规则清单 | docs/验证规则清单_v1.0.md |
验证引擎 34 条规则显性化(G/A/T/D/I/E/M 七族,含变更流程与测试映射) |
- 金标数量 620 篇(2026-08-21 十源扩标收官,合集
tests/fixtures/gold/gold_dataset_v4.json),已超 v4.1 推荐 300~350 篇;全量 620 篇复测已完成(2026-08-21):D 组 field_precision 97.60%、unjustified_rate 0.00%、evidence_precision 99.91%、null_false_positive_rate 0.57%(详见上文复测小节) - 未划分开发集/校准集/测试集:当前为统一金标集
- temperature 记录口径:记录 0.0,实际 0.1,不影响指标结论,后续修复
- Demo 视频:复赛阶段已有录屏演示脚本(
scripts/record_demo.py),场景 5/8 使用 id=114 东南大学主线(证据可重放),正式视频待录制 - 10+ 个官方来源适配器:ccgp 中央 + ggzy 全国 + 粤/苏/滇/鲁/津/青岛/豫/浙/粤九省,商业平台暂不接入
| 层 | 技术 |
|---|---|
| 后端框架 | Python 3.11+ / FastAPI |
| Agent 框架 | 纯 Python 轻量级实现(不依赖 langgraph) |
| 抓取引擎 | Playwright (async API) + httpx AsyncClient |
| LLM | DeepSeek(默认)/ Ollama / vLLM(私有化部署 keyless 模式) |
| 任务调度 | APScheduler + croniter |
| 去重算法 | jieba 分词 + 64 位 SimHash |
| 证据存证 | SHA-256 入库哈希 + 重放核验 + 生命周期链 |
| 数据库 | SQLite (MVP) → PostgreSQL (生产) |
| ORM | SQLAlchemy 2.0 async + aiosqlite |
| 部署 | Docker 多阶段构建 + non-root 用户 + healthcheck |
| 私有化部署 | 本地 Ollama / vLLM 无 key 模式 + 模型就绪检查器 |
- 所有中间件用 async/await,不用 callback 风格
- API Key 用 HMAC-SHA256 摘要 + Argon2id 密码哈希 + AES-GCM Cookie 加密
- 环境变量密钥用
secrets.token_hex(32)生成 64 字符 hex - SSRF 三层防护 / LIKE 注入防护 / 邮件头注入防护 / 路径穿越防护
- 异步函数用
run_in_executor卸载同步 CPU/IO 任务 - 结构化日志带 request_id 上下文,不记录凭证
- 统一错误响应
{code, data, msg} - Docker 多阶段构建 + non-root 用户 + healthcheck
- GitHub Actions CI:pytest 稳定子集(排除 4 个时序敏感/E2E 文件,单测 180s 超时兜底、偶发失败自动重跑)+ 覆盖率 40% 阈值 + pip-audit 依赖漏洞扫描(.github/workflows/ci.yml);全量 2435 用例在开发机本地执行
Apache License 2.0
- 团队:标小智(徐浚钊、王祯明)
- 所属:上海建桥大学 计算机科学与技术专业
- 赛事:GOAI 世界人工智能开源大赛 · 无界应用赛道 · AI+金融方向
- 仓库:https://github.com/tlyyxjz/BidAgent