Files
Profeto/docs/07-development.md
T
shangfangjian c657e04679 docs: 同步文档与实现一致性
- 5 张表 → 6 张表(添加 injuries)
- 同步所有 docs 和 models.py docstring
2026-09-15 01:44:49 +08:00

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, "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. 新增数据源

  1. src/data/ 写采集模块(参考 understat.py)
  2. normalize.py 加清洗函数
  3. context_builder.py 加切片函数
  4. api/routes/ingest.py 加端点
  5. 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/)