- 修复所有 confidence → subjective_confidence 残留(03-api, 04-agents, 05-data, 07-development) - 修复 5 张表 → 6 张表残留(06-deployment) - 同步 API schema 示例与实际模型一致 - 更新 predictions 表结构文档(新增 status/cutoff/input_hash 字段) code: 修复 API 异常处理(eval/predict)和 context_builder stats 时间过滤
6.3 KiB
6.3 KiB
07 · 开发指南
本地开发环境搭建
# 1. 克隆并进入项目
cd Profeto
# 2. 安装依赖(含 dev)
pip install -e ".[dev]"
# 3. 启动 PostgreSQL
docker run -d --name profeto-pg \
-e POSTGRES_USER=football -e POSTGRES_PASSWORD=football -e POSTGRES_DB=football \
-p 5432:5432 postgres:16-alpine
# 4. 配置环境变量
cp .env.example .env
# 编辑 .env 填 LLM_API_KEY / BZZOIRO_KEY
# 5. 建表
alembic upgrade head
# 6. 启动 API(热重载)
uvicorn src.api.app:app --reload
# 7. 启动前端(另一个终端)
cd frontend && npm install && npm run dev
项目结构
Profeto/
├── src/ # 后端源码
│ ├── api/
│ │ ├── routes/ # FastAPI 路由
│ │ │ ├── leagues.py # 联赛/比赛查询
│ │ │ ├── predict.py # 预测入口
│ │ │ ├── ingest.py # 数据采集
│ │ │ └── eval.py # 评估回填
│ │ ├── schemas.py # Pydantic 模型
│ │ └── app.py # FastAPI 工厂
│ ├── db/
│ │ ├── base.py # SQLAlchemy async engine + session
│ │ └── models.py # 6 张表 ORM
│ ├── data/
│ │ ├── bzzoiro.py # bzzoiro 采集 + 入库
│ │ ├── understat.py # understat xG 回填
│ │ ├── injuries.py # 伤停采集
│ │ ├── normalize.py # 数据清洗契约
│ │ ├── team_names.py # 队名归一化映射
│ │ └── config.py # 联赛映射常量
│ ├── llm/
│ │ ├── provider.py # LLM 提供商抽象(OpenAI-compatible)
│ │ ├── context_builder.py # 数据切片 + 拼接
│ │ ├── predict.py # 预测入口(单/多模式分派)
│ │ ├── eval.py # 评估统计
│ │ ├── agents/
│ │ │ ├── base.py # AgentSpec + run_agent
│ │ │ └── orchestrator.py # 多 agent 编排
│ │ └── prompts/
│ │ ├── match_prediction_v1.md # 单 agent prompt
│ │ └── agents/ # 多 agent prompt
│ │ ├── form_v1.md
│ │ ├── stats_v1.md
│ │ ├── home_away_v1.md
│ │ ├── injuries_v1.md
│ │ ├── h2h_v1.md
│ │ └── aggregator_v1.md
│ └── core/
│ └── config.py # pydantic-settings 配置
├── frontend/ # React 单页前端
├── alembic/ # 数据库迁移
│ └── versions/
│ ├── 0001_initial.py
│ └── 0002_agent_outputs.py
├── tests/ # 测试
│ ├── test_core.py # 核心逻辑测试
│ └── test_agents.py # 多 agent 测试
├── docs/ # 本文档
├── pyproject.toml # 依赖 + 构建配置
├── alembic.ini # Alembic 配置
├── Dockerfile # 生产镜像
├── docker-compose.yml # 本地/生产编排
└── .env.example # 环境变量模板
测试
# 跑全部测试
pytest
# 详细输出
pytest -v
# 只跑 agent 测试
pytest tests/test_agents.py -v
# 覆盖率
pytest --cov=src --cov-report=term-missing
当前测试覆盖:
test_core.py(13 项):数据清洗、队名归一、赛季标签、LLM 解析test_agents.py(20 项):no_data 门控、fail-open、prompt 加载、报告解析、终裁渲染
写新测试的模式
mock LLM 提供商(避免真实调用):
class MockProvider:
model = "test-model"
async def chat(self, system, user, **kw):
from src.llm.provider import LLMResponse
return LLMResponse(
content="{}",
parsed={"data_sufficiency": "high", "analysis": "ok",
"home_edge": 0.5, "subjective_confidence": 0.8,
"key_evidence": ["证据"]},
prompt_tokens=10, completion_tokens=5, latency_ms=100,
)
常见开发任务
1. 修改 Agent Prompt
直接编辑 src/llm/prompts/agents/{name}_v1.md,无需重启(有 lru_cache,改完清缓存或重启)。
迭代版本:
cp src/llm/prompts/agents/h2h_v1.md src/llm/prompts/agents/h2h_v2.md
# 编辑 h2h_v2.md
# 调用时传 prompt_version: "v2"
2. 新增 Agent
见 04-agents.md § 如何新增一个专家 Agent。
3. 新增数据源
- 在
src/data/写采集模块(参考understat.py) - 在
normalize.py加清洗函数 - 在
context_builder.py加切片函数 - 在
api/routes/ingest.py加端点 - 在
api/schemas.py加请求/响应模型
4. 新增联赛
编辑 src/data/config.py:
BZZOIRO_LEAGUE_IDS["新代码"] = league_id
LEAGUE_NAMES["新代码"] = "联赛名"
LEAGUE_COUNTRIES["新代码"] = "国家"
5. 数据库 Schema 变更
# 1. 改 src/db/models.py
# 2. 生成迁移
alembic revision --autogenerate -m "描述"
# 3. 检查生成的迁移文件(自动推断不完美)
# 4. 应用
alembic upgrade head
前端开发
cd frontend
npm install
npm run dev # 开发(热重载,代理 /api → localhost:8000)
npm run build # 生产构建 → dist/
npm run preview # 预览生产构建
技术栈:React + TypeScript + Tailwind CSS + Vite。
主要页面:src/pages/Matches.tsx(比赛列表 + 预测 + agent 报告展示)。
编码约定
- 异步优先:所有 IO 用
async/await,SQLAlchemy 用 async session - session 管理:
- 路由读操作:依赖注入
get_db_read(不自动 commit) - 路由写操作:依赖注入
get_db(自动 commit) - 内部/ingest:直接用
AsyncSessionLocal()自己管事务
- 路由读操作:依赖注入
- 错误处理:领域层抛
ValueError/RuntimeError,路由层转 HTTP 状态码 - 日志:用
logging.getLogger(__name__),关键路径打 info/debug - 类型提示:全量标注,
Mapped[T]+mapped_column
提交前检查清单
# 1. 测试全绿
pytest
# 2. 语法检查
python -m py_compile src/**/*.py
# 3. 确认 .env 不提交(已在 .gitignore)
# 4. 文档同步(改功能时更新 docs/)