feat: 足球 LLM 预测服务初始提交
Profeto — 给 LLM 提供数据,让 LLM 预测足球比分。 核心模块: - FastAPI 后端 + PostgreSQL (SQLAlchemy async) - 多 Agent LLM 预测 (5 专家 + 终裁) - 数据采集 (bzzoiro / understat / injuries) - React 前端 (Vite + Tailwind) 包含: - 数据源抽象 (DataSource 协议 + 注册表) - Alembic 数据库迁移 - Prompt 模板 (单/多 Agent) - 核心路径单元测试
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
"""Pydantic schemas。"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class LeagueOut(BaseModel):
|
||||
id: int
|
||||
code: str
|
||||
name: str
|
||||
country: str | None
|
||||
|
||||
|
||||
class MatchOut(BaseModel):
|
||||
id: int
|
||||
league_code: str | None
|
||||
season: str | None
|
||||
home_team: str
|
||||
away_team: str
|
||||
home_team_zh: str | None
|
||||
away_team_zh: str | None
|
||||
match_date: datetime
|
||||
match_status: str
|
||||
home_goals: int | None
|
||||
away_goals: int | None
|
||||
match_stage: str | None
|
||||
home_xg: float | None = None
|
||||
away_xg: float | None = None
|
||||
|
||||
|
||||
class MatchListOut(BaseModel):
|
||||
items: list[MatchOut]
|
||||
next_cursor: str | None
|
||||
has_more: bool
|
||||
|
||||
|
||||
class PredictRequest(BaseModel):
|
||||
match_id: int
|
||||
provider: str | None = None
|
||||
model: str | None = None
|
||||
prompt_version: str | None = None
|
||||
mode: str = "multi" # multi(默认, 5专家+终裁) | single(单次调用)
|
||||
|
||||
|
||||
class PredictOut(BaseModel):
|
||||
prediction_id: int
|
||||
provider: str
|
||||
model: str
|
||||
prompt_version: str | None = None
|
||||
mode: str = "single"
|
||||
pred_home_goals: float | None
|
||||
pred_away_goals: float | None
|
||||
pred_1x2: str | None
|
||||
confidence: float | None
|
||||
reasoning: str | None
|
||||
agent_outputs: list[dict] | None = None
|
||||
agent_weights: dict | None = None
|
||||
context: str
|
||||
latency_ms: int | None
|
||||
|
||||
|
||||
class PredictionOut(BaseModel):
|
||||
id: int
|
||||
match_id: int
|
||||
provider: str
|
||||
model: str
|
||||
prompt_version: str
|
||||
mode: str = "single"
|
||||
pred_home_goals: float | None
|
||||
pred_away_goals: float | None
|
||||
pred_1x2: str | None
|
||||
confidence: float | None
|
||||
reasoning: str | None
|
||||
agent_outputs: list[dict] | None = None
|
||||
created_at: datetime
|
||||
actual_home_goals: int | None
|
||||
actual_away_goals: int | None
|
||||
settled: bool
|
||||
|
||||
|
||||
class IngestBzzoiroRequest(BaseModel):
|
||||
leagues: list[str] = Field(..., description="联赛代码列表,如 ['E0','SP1']")
|
||||
date_from: str | None = None
|
||||
date_to: str | None = None
|
||||
status: str = "finished"
|
||||
|
||||
|
||||
class IngestResponse(BaseModel):
|
||||
leagues: dict
|
||||
total_inserted: int
|
||||
total_updated: int
|
||||
errors: list[str] = []
|
||||
|
||||
|
||||
class IngestUnderstatRequest(BaseModel):
|
||||
league: str = Field(..., description="联赛代码,如 'E0'")
|
||||
season: int = Field(..., description="赛季起始年,如 2025 表示 2025-2026 赛季")
|
||||
|
||||
|
||||
class IngestInjuriesRequest(BaseModel):
|
||||
date: str | None = Field(None, description="日期 YYYY-MM-DD,为空则采集当天")
|
||||
|
||||
|
||||
class IngestSimpleResponse(BaseModel):
|
||||
count: int = 0
|
||||
updated: int = 0
|
||||
skipped: int = 0
|
||||
unmatched: int = 0
|
||||
errors: list[str] = []
|
||||
|
||||
|
||||
class SettleRequest(BaseModel):
|
||||
prediction_id: int
|
||||
home_goals: int = Field(ge=0, le=30)
|
||||
away_goals: int = Field(ge=0, le=30)
|
||||
|
||||
|
||||
class EvalSummaryOut(BaseModel):
|
||||
summary: list[dict[str, Any]]
|
||||
Reference in New Issue
Block a user