Files
Profeto/README.md
T
WorkBuddy 6bdb1f8ae6 docs(deploy): 补充生产上线检查清单(README + docs/06)
- docs/06 新增「生产上线检查清单」10 项:APP_ENV / SECRET_KEY 强随机 /
  管理鉴权二选一 / 数据库强密码 / HTTPS+Cookie Secure /
  TRUST_PROXY_HEADERS+X-Forwarded-For / Nginx limit_req 限流前置
  (应用内限流与 KeyRing 单进程限制) / uvicorn 单 worker /
  /health 与 /health/ready / alembic 迁移已内置
- README 在部署说明后加同名精简清单,链接到 docs/06 详情
- 全部条目均对齐真实实现(security_check 弱值黑名单、auth.py
  secure=production、deps.py TRUST_PROXY 解析、app.py 双健康检查、
  compose/Dockerfile 内置迁移);纯文档,未改业务逻辑
2026-09-21 21:02:16 +08:00

12 KiB

Profeto — 先知

给 LLM 提供结构化数据,让 LLM 预测足球比分。

架构

┌─────────────────────────────────────────────────────┐
│  前端 (React + Vite + Tailwind)                     │
│  http://localhost:5173                              │
└──────────────────────┬──────────────────────────────┘
                       │ REST API
┌──────────────────────▼──────────────────────────────┐
│  FastAPI                                            │
│  ├── /api/v1/matches     比赛查询(公开只读)          │
│  ├── /api/v1/predict     LLM 预测 (单/多 Agent)     │
│  ├── /api/v1/ingest/*    数据采集(需管理员)          │
│  ├── /api/v1/eval/*      评估回填(需管理员)          │
│  └── /api/v1/backtest    回测(需管理员)              │
└──────────┬─────────────────────────────┬────────────┘
           │                             │
┌──────────▼──────────┐    ┌─────────────▼────────────┐
│  PostgreSQL         │    │  LLM (OpenAI-compatible)  │
│  12 张表            │    │  OpenAI / Deepseek /      │
│  leagues/teams/     │    │  Ollama / 任意网关        │
│  matches/match_     │    └──────────────────────────┘
│  stats/standings/   │
│  predictions/       │
│  app_settings/      │
│  schedules +        │
│  raw_events 等 4 张 │
│  数据治理表          │
└─────────────────────┘
           ▲
           │ 采集
┌──────────┴─────────────────────────────────────────┐
│  数据源 (DataSource 协议 + 注册表)                   │
│  └── bzzoiro    比分 / 赛程 / 统计 / 积分榜          │
└────────────────────────────────────────────────────┘

分层架构

API Route → Application Service → Repository → UnitOfWork → DB
  • UnitOfWork: 统一事务边界,业务层不再自行 commit
  • Repository: 封装数据访问,提供类型化查询接口
  • DataSource: 采集外部数据,通过注册表动态分发

多 Agent 预测

默认模式 (mode=multi) 采用 5 专家 + 终裁 架构:

比赛数据 → 切片 ─┬─→ A 近期状态专家 ─┐
                 ├─→ B 攻防数据专家 ─┤
                 ├─→ C 主客因素专家 ─┼─→ 终裁专家 ─→ 最终预测
                 ├─→ D 联赛排名专家 ─┤
                 └─→ E 历史交锋专家 ─┘
  • 各专家只看到自己维度的数据切片,避免信息过载
  • fail-open: 单个专家失败不影响整体
  • no_data 门控: 无数据维度跳过 LLM 调用,省 token 防幻觉
  • 终裁根据各报告的 subjective_confidence / data_sufficiency 输出 agent_weights

数据正确性保障

  • Cutoff 机制: 回测时只使用 cutoff_at 之前已采集的数据(近况/交锋/统计/积分榜切片统一生效)
  • LLM 输出校验: Pydantic 严格校验 + 语义一致性检查
  • 数据库约束: CHECK 约束作为最后一道防线

快速开始

前置条件

  • Python >= 3.11
  • Docker (运行 PostgreSQL)
  • LLM API Key (OpenAI / Deepseek / Ollama 等)

方式一:Docker Compose 部署(推荐)

# 1. 克隆仓库
git clone https://git.bilidili.cn/shangfangjian/Profeto.git
cd Profeto

# 2. 配置环境变量
cp .env.example .env
# 编辑 .env,填入 LLM_API_KEY 和 BZZOIRO_KEY

# 3. 启动全部服务(自动构建 + 执行迁移)
docker compose up -d --build

# 4. 验证
curl http://localhost:8000/health

启动后访问:

说明: api 容器启动时自动执行 alembic upgrade head,无需手动运行迁移。

方式二:本地开发部署

# 1. 克隆 + 安装
git clone https://git.bilidili.cn/shangfangjian/Profeto.git
cd Profeto
pip install -e ".[dev]"

# 2. 配置环境变量
cp .env.example .env
# 编辑 .env,填入 LLM_API_KEY 和 BZZOIRO_KEY

# 3. 启动 PostgreSQL
docker compose up -d postgres

# 4. 执行迁移
alembic upgrade head

# 5. 启动后端 (终端 1)
uvicorn src.api.app:app --reload

# 6. 启动前端 (终端 2)
cd frontend && npm install && npm run dev

后端运行在 http://localhost:8000,前端在 http://localhost:5173

生产上线检查清单

公网部署前逐项确认(第 1–4 项由启动校验强制,不满足拒绝启动;详见 docs/06-deployment.md):

  • APP_ENV=production(安全校验 / Cookie Secure / 管理端点 fail-closed 的总开关)
  • SECRET_KEY 强随机:openssl rand -base64 32,禁止弱值
  • ADMIN_PASSWORDADMIN_API_KEY 至少配置其一
  • 数据库强密码,禁止 football:football 等示例弱密码
  • HTTPS(反代终结 TLS;production 下会话 Cookie 自动 Secure)
  • 反代后设 TRUST_PROXY_HEADERS=True,仅可信反代可达 API,并配置 X-Forwarded-For / X-Real-IP
  • 限流前置到 Nginx limit_req;应用内限流与 KeyRing 仅单进程有效,多 worker 会放大配额
  • uvicorn 单 worker(默认);需扩容先网关统一限流再起多实例
  • 启动后验证 /health/health/ready 均 200
  • 数据库迁移已内置:compose/Dockerfile 启动即执行 alembic upgrade head

安全与限流

  • /api/v1/predict: 内存滑动窗口限流(10 次/分钟/IP),多 worker 时每进程独立计数
  • 登录防爆破: 进程内内存计数,同上
  • 公网部署建议 Nginx 层限流 + TRUST_PROXY_HEADERS=True
  • 生产环境必须配置 ADMIN_PASSWORDADMIN_API_KEY(否则管理接口 503)

详见 docs/06-deployment.md

API 概览

公开只读(无需登录;predict 带内存限流):

方法 路径 说明
GET /api/v1/leagues 联赛列表(仅 id/code/name/country)
GET /api/v1/matches 比赛查询(筛选/游标分页)
GET /api/v1/matches/{id} 比赛详情(含统计与最近预测)
GET /api/v1/matches/{id}/context 比赛上下文(双方近况 + 历史交锋)
GET /api/v1/standings 联赛积分榜
POST /api/v1/predict LLM 预测 (mode=single/multi/baseline)
GET /health/health/ready 存活 / 就绪检查(含 DB)

需管理员(Cookie 会话或 X-API-Key):

方法 路径 说明
POST /api/v1/ingest/bzzoiro 采集赛果/赛程/统计/积分榜
GET /api/v1/predictions 预测历史(列表)
GET /api/v1/predictions/{id} 单条预测详情
POST /api/v1/eval/settle 回填实际结果
GET /api/v1/eval/summary 准确率汇总
POST /api/v1/backtest 历史回测
/api/v1/admin/** 配置/采集状态/日志/定时任务/死信等 管理后台(router 级鉴权)

项目结构

Profeto/
├── src/
│   ├── api/                    # FastAPI 路由层
│   │   ├── app.py              # 应用工厂 + lifespan
│   │   ├── deps.py             # 依赖注入:鉴权 / 限流
│   │   ├── schemas.py          # Pydantic 请求/响应模型
│   │   └── routes/
│   │       ├── matches.py      # 比赛查询(公开只读)
│   │       ├── predict.py      # 预测入口 + 预测历史
│   │       ├── ingest.py       # 数据采集(需管理员)
│   │       ├── eval.py         # 评估回填(需管理员)
│   │       ├── backtest.py     # 回测(需管理员)
│   │       ├── auth.py         # 登录/登出/改密
│   │       ├── admin_settings.py  # /admin/** 配置/日志/数据质量(router 级鉴权)
│   │       └── schedules.py    # 定时任务 + 死信重试(router 级鉴权)
│   ├── core/                   # 基础设施
│   │   ├── config.py           # pydantic-settings 配置
│   │   ├── crypto.py           # 加密/哈希
│   │   ├── http_client.py      # 共享 httpx 客户端
│   │   ├── log_buffer.py       # 内存日志缓冲(admin 日志页)
│   │   ├── runtime_config.py   # DB 配置覆盖(.env → app_settings)
│   │   ├── scheduler.py        # 进程内 cron 调度器
│   │   └── security_check.py   # 启动安全校验
│   ├── data/                   # 数据层
│   │   ├── sources.py          # DataSource 协议 + 注册表
│   │   ├── bzzoiro.py          # bzzoiro 数据源(events/standings/stats)
│   │   ├── normalize.py        # 数据规范化契约
│   │   ├── config.py           # 联赛映射常量
│   │   ├── key_ring.py         # API Key 轮换环(429 冷却)
│   │   ├── team_names.py       # 队名归一化
│   │   └── team_names_zh.py    # 队名中文映射
│   ├── db/                     # 数据库
│   │   ├── base.py             # SQLAlchemy async engine
│   │   ├── models.py           # ORM 模型 (12 表)
│   │   ├── unit_of_work.py     # UnitOfWork 事务封装
│   │   └── repositories.py     # Repository 数据访问
│   └── llm/                    # LLM 预测核心
│       ├── predict.py          # 预测服务 (缓存 + 单/多/基线模式)
│       ├── context_builder.py  # 数据切片 + 上下文拼接
│       ├── baseline.py         # 基线预测(均值模型)
│       ├── eval.py             # 评估统计
│       ├── backtest.py         # 回测框架
│       ├── provider.py         # 多提供商 LLM 抽象
│       ├── utils.py            # LLM 工具函数
│       ├── validation.py       # LLM 输出校验
│       ├── agents/
│       │   ├── base.py         # Agent 基础设施 + 解析
│       │   └── orchestrator.py # 多 Agent 编排
│       └── prompts/            # Prompt 模板
├── alembic/                    # 数据库迁移
├── frontend/                   # React 前端
│   └── src/
│       ├── pages/              # 公开站(赛程 Matches + 积分榜 Standings)
│       ├── admin/              # 管理后台(布局/页面/数据访问层 dal.ts)
│       ├── components/         # 共享组件
│       └── lib/http.ts         # 唯一 HTTP 实现(带凭据/超时/错误处理)
├── docs/                       # 详细文档
├── tests/                      # 单元测试
├── docker-compose.yml
├── Dockerfile
└── pyproject.toml

核心模块

模块 作用
context_builder.py 最重要: 数据切片 + 拼接 LLM 看到的上下文
prompts/ Prompt 模板 (迭代最频繁)
provider.py OpenAI-compatible 多提供商抽象
sources.py 数据源协议 + 注册表
unit_of_work.py 统一事务边界
repositories.py 数据访问封装
validation.py LLM 输出严格校验
backtest.py 回测框架(防未来数据泄漏)

配置

通过 .env 或环境变量配置:

变量 说明 默认值
DATABASE_URL PostgreSQL 连接 postgresql+asyncpg://football:football@localhost:5432/football
LLM_PROVIDER 提供商标识 openai
LLM_API_KEY API 密钥 (必填)
LLM_BASE_URL API 地址 https://api.openai.com/v1
LLM_MODEL 模型名 gpt-4o
LLM_SPECIALIST_MODEL 专家模型 (空=回落 LLM_MODEL)
LLM_AGGREGATOR_MODEL 终裁模型 (空=回落 LLM_MODEL)
BZZOIRO_KEY bzzoiro API Key (必填)
CORS_ORIGINS 允许的跨域来源 http://localhost:5173

测试

pytest

数据库迁移

alembic upgrade head

License

个人研究项目,预测结果不构成投注建议。