Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ All three consume the same core:

- `src/agents/` — N25-N31 multi-agent stack (pace, tire, race situation,
pit strategy, radio NLP, RAG regulations, orchestrator).
- `src/strategy/inference/engine.py::run_lap` — the single shared per-lap
pipeline call that the CLI, Arcade, and backend all route through
(profiles: `rich` for the full LLM-synthesis path, `no-llm` for the
deterministic zero-LLM-client path). Replaces three hand-mirrored
copies of the orchestrator sequence that used to drift out of sync.
- `src/simulation/` — `RaceReplayEngine` + `RaceStateManager`.
- `data/processed/laps_featured_<year>.parquet` + `data/raw/<year>/<Location>/` +
`data/tire_compounds_by_race.json`.

The Streamlit path also runs a FastAPI backend (`src/telemetry/backend/`).
The Arcade path runs the strategy pipeline locally without the backend
(see [`docs/pages/arcade-strategy-pipeline.md`](docs/pages/arcade-strategy-pipeline.md)).
The Arcade path calls `run_lap` in-process without going through the
backend (see [`docs/pages/arcade-strategy-pipeline.md`](docs/pages/arcade-strategy-pipeline.md)).

## Multi-agent pipeline

Expand Down Expand Up @@ -54,7 +59,7 @@ Both windows subscribe to the arcade's `TelemetryStreamServer` on
- Featured laps parquets + per-race raw dirs + tire-compound-by-race
map form the input to the multi-agent stack.

for the wire-level view.
See [`docs/pages/simulation.md`](docs/pages/simulation.md) for the wire-level view.

## Where to go next

Expand Down
51 changes: 39 additions & 12 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ after merge.
## Development setup

```bash
git clone https://github.com/VforVitorio/F1_Strat_Manager.git
cd F1_Strat_Manager
git clone https://github.com/VforVitorio/F1-StratLab.git
cd F1-StratLab
git submodule update --init --recursive # src/telemetry/ is a submodule
uv sync # installs every dependency
cp .env.example .env # add OPENAI_API_KEY here
Expand All @@ -34,13 +34,15 @@ Run once to pre-populate the data cache on first launch:
python -c "from src.f1_strat_manager.data_cache import ensure_setup; ensure_setup(show_progress=True)"
```

Three entry points after install (`pyproject.toml::[project.scripts]`):
Five entry points after install (`pyproject.toml::[project.scripts]`):

| Command | What it runs |
|---|---|
| `f1-sim` | CLI strategy simulation with Rich live panel |
| `f1-strat` | Interactive CLI wizard (arrow-key pickers for race / driver / provider); shells out to `f1-sim` |
| `f1-sim` | Headless CLI strategy simulation with Rich live panel (the scripted form) |
| `f1-arcade --strategy` | 2D replay + PySide6 dashboard + telemetry |
| `f1-streamlit` | Post-race analysis + chat UI |
| `f1-eval` | Regenerates the model evaluation reports (`registry`, `calibration`, `hygiene`, `nlp`, `models`, `alert-llm` subcommands) under `documents/eval_reports/` |

## Code style

Expand Down Expand Up @@ -71,9 +73,10 @@ Some code carries hard rules set by the TFG author:
- **`scripts/run_simulation_cli.py`** — the TFG's PMV (first working
CLI). Duplicate before modifying; do not refactor in-place.
- **`src/agents/` internals** — stable contract for the CLI + Streamlit
+ Arcade paths. Additive entry points are welcome (see the verbose
variant in `src/arcade/strategy_pipeline.py`), but do not refactor
existing ones.
+ Arcade paths. Additive entry points are welcome (see
`src/strategy/inference/engine.py::run_lap`, the shared per-lap pipeline
call all three surfaces route through), but do not refactor existing
agent modules in place.
- **`notebooks/**`** and **`legacy/**`** — exploration / historical
archive, different conventions.

Expand Down Expand Up @@ -127,13 +130,20 @@ these safeguards trigger there. They are no-ops on POSIX.

## CI pipeline

Three parallel jobs run on every push and PR (`.github/workflows/ci.yml`):
Four jobs run on every push and PR (`.github/workflows/ci.yml`):

| Job | Installs | Runs |
|---|---|---|
| `lint` | nothing — ruff via `uvx` | `ruff check .` + `ruff format --check .` |
| `typecheck` | `uv sync --extra dev` (mypy + project deps, no voice extras) | `mypy src/rag/` |
| `test` | `uv sync --all-extras` (full ML/voice/arcade stack) | `pytest -v` |
| `test` | `uv sync --all-extras` (full ML/voice/arcade stack) | `pytest -v --cov=src` + a collected-test-count floor (guards against a refactor silently dropping the suite) |
| `pip-audit` | `uv export` to a requirements file | `pip-audit` against the locked deps (advisory, `continue-on-error: true` while baselining) |

`test` and `typecheck` are additionally gated by `dorny/paths-filter`:
they skip their real work (still reporting green) when the diff touches
neither `src/`, `tests/`, `pyproject.toml`, `uv.lock`, nor the workflow
file itself — a docs-only or CI-only PR does not pay for a full ML-stack
install. `lint` and `pip-audit` stay always-on.

All jobs share uv's wheel cache (`enable-cache: true`, keyed off
`uv.lock`), so the cache only invalidates when the resolved graph
Expand All @@ -159,7 +169,7 @@ at once and stranded them for 20+ minutes.
### PR labels

Every pull request gets auto-tagged with one or more `area:` labels by
`.github/workflows/labeler.yml` (path-based via `actions/labeler@v5`).
`.github/workflows/labeler.yml` (path-based via `actions/labeler@v6`).
Dependabot PRs additionally get their label set by `dependabot.yml` so
the tag is in place the moment the PR opens — no need to wait for the
labeler workflow to run.
Expand Down Expand Up @@ -219,11 +229,28 @@ accepting a bump that breaks something:
import paths, `np.bool_` alias). Grows whenever a new upstream
incident reveals a fragile call site.

### Security workflows

Three additional workflows run independently of `ci.yml`, all scoped to
the parent repo (the `src/telemetry` submodule has its own scanner
coverage, tracked separately):

- **CodeQL** (`.github/workflows/codeql.yml`) — SAST on Python and the
`docs/` React SPA, `security-extended` query suite, on push/PR to
`main`/`dev` plus a weekly schedule.
- **gitleaks** (`.github/workflows/gitleaks.yml`) — secret scanning over
full history on push/PR plus a weekly schedule, complementing GitHub's
native secret scanning.
- **OSV-Scanner** (`.github/workflows/osv-scanner.yml`) — cross-ecosystem
vulnerability scan against OSV.dev on `uv.lock`; blocking (any new,
un-waived CVE fails the build). Known unfixable CVEs (Pillow, torch,
ecdsa) are waived with documented reasons in `osv-scanner.toml`.

## Issue templates

File an issue via the GitHub UI. Three templates are available under
File an issue via the GitHub UI. Four templates are available under
[.github/ISSUE_TEMPLATE/](.github/ISSUE_TEMPLATE): bug report, feature
request, data issue.
request, data issue, epic.

## Related reading

Expand Down
38 changes: 25 additions & 13 deletions INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The project integrates several ML stacks — XGBoost/LightGBM for race strategy

The current development phase (N25–N31) replaces the legacy Experta rule engine with a **LangGraph multi-agent architecture**: specialised sub-agents (pace, tyre, overtake, safety car, pit strategy, radio NLP, regulation RAG) coordinate under a Supervisor Orchestrator.

> For full documentation see the [README](README.md) and the [DeepWiki](https://deepwiki.com/VforVitorio/F1_Strat_Manager). For the deep reference (methodology, metrics, design rationale): the **TFG thesis + IEEE technical report** in [`documents/thesis/`](documents/thesis/). Legacy paper: [F1_Strategy_Manager_AI.pdf](documents/docs_legacy_strat_manager/F1_Strategy_Manager_AI.pdf).
> For full documentation see the [README](README.md) and the [DeepWiki](https://deepwiki.com/VforVitorio/F1-StratLab). For the deep reference (methodology, metrics, design rationale): the **TFG thesis + IEEE technical report** in [`documents/thesis/`](documents/thesis/). Legacy paper: [F1_Strategy_Manager_AI.pdf](documents/docs_legacy_strat_manager/F1_Strategy_Manager_AI.pdf).

Notebooks are the primary development artefact. `src/` modules are extracted from notebooks only when they need to be imported by other notebooks or the telemetry app.

Expand Down Expand Up @@ -89,6 +89,7 @@ Notebooks are the primary development artefact. `src/` modules are extracted fro
| [N22_ner_models.ipynb](notebooks/nlp/N22_ner_models.ipynb) | F1-domain NER on short radio transcriptions; BERT-large CoNLL-03 BIO token classifier (F1 = 0.42); documents GLiNER zero-shot and fine-tuning failures |
| [N23_rcm_parser.ipynb](notebooks/nlp/N23_rcm_parser.ipynb) | Rule-based structured event extractor for FastF1 `race_control_messages`; deterministic, no ML required |
| [N24_nlp_pipeline.ipynb](notebooks/nlp/N24_nlp_pipeline.ipynb) | Unified inference pipeline merging N20-N23: sentiment + intent + NER + RCM parsing; GPU P95 latency 59.4 ms; exports `pipeline_config_v1.json` |
| [N33_radio_dataset_builder.ipynb](notebooks/nlp/N33_radio_dataset_builder.ipynb) | Builds the static per-GP OpenF1 radio corpus (parquets + MP3s) consumed at replay time by `src/nlp/radio_runner.py`; the CLI's `ensure_radio_corpus()` downloads this corpus lazily per GP |

### Agents (`notebooks/agents/`)

Expand All @@ -98,7 +99,7 @@ Notebooks are the primary development artefact. `src/` modules are extracted fro
| [N30_rag_agent.ipynb](notebooks/agents/N30_rag_agent.ipynb) | RAG Agent — retrieval-augmented generation over FIA Sporting and Technical Regulations (2023-2025) via local Qdrant; returns structured `RegulationContext` objects with article references |
| [N34_radio_runner_smoke.ipynb](notebooks/agents/N34_radio_runner_smoke.ipynb) | Radio runner smoke test — end-to-end validation of `src/nlp/radio_runner.py`: cache hit/miss, per-lap radio distribution, transcript sanity, and N29 round-trip via `run_radio_agent_from_state` on Bahrain 2025 (28 radios + 76 RCMs, lap 4 emits a PROBLEM alert) |

> The full multi-agent system (N25–N31) is **complete**. The importable agent + orchestrator modules live in [`src/agents/`](src/agents/) (each exposes `run_*_agent_from_state`). Notebooks N26–N29, N31, plus N33 (decision thresholds + calibration benchmarks) and N34 (radio runner smoke) are under `notebooks/agents/`.
> The full multi-agent system (N25–N31) is **complete**. The importable agent + orchestrator modules live in [`src/agents/`](src/agents/) (each exposes `run_*_agent_from_state`). Notebooks N26–N29, N30B (RAG benchmark), two N31 notebooks (`N31_strategy_orchestrator.ipynb` + `N31_mc_visualization.ipynb`), N32 (smoke test), N33 (decision thresholds + calibration benchmarks), and N34 (radio runner smoke) are under `notebooks/agents/`. A different, unrelated `N33_radio_dataset_builder.ipynb` lives under `notebooks/nlp/` (see the NLP table below) — the two share a number by coincidence, not by pipeline order.

---

Expand Down Expand Up @@ -142,24 +143,35 @@ The two files below are the **legacy** `experta` rule engine, kept for reference

### `src/strategy/`

`inference/engine.py` is **production**: it is the single shared implementation
of the per-lap N31 pipeline, and the CLI, Arcade, and FastAPI backend all route
through it instead of maintaining hand-mirrored copies (a real drift bug once
caused every `--no-llm` lap to crash, since a signature change was mirrored
into two of the three copies but not the third). `eval/` backs the `f1-eval`
console script. The jupytext-exported `models/` files and `training/` (empty)
are reference/historical only — see [`src/strategy/README.md`](src/strategy/README.md).

| File | Description |
| ---------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| [src/strategy/models/lap_time_model.py](src/strategy/models/lap_time_model.py) | Jupytext-exported lap time model module |
| [src/strategy/models/tire_degradation_model.py](src/strategy/models/tire_degradation_model.py) | Jupytext-exported tire degradation model module |
| [src/strategy/inference/tire_predictor.py](src/strategy/inference/tire_predictor.py) | Jupytext-exported tire degradation inference wrapper |
| [src/strategy/inference/engine.py](src/strategy/inference/engine.py) | `run_lap()` — the shared strategy inference engine consumed by the CLI, Arcade, and backend; dispatches on `profile` (`"rich"` re-drives the full N31 orchestrator sequence, `"no-llm"` is the deterministic zero-LLM-client path) |
| [src/strategy/inference/no_llm.py](src/strategy/inference/no_llm.py) | The deterministic `--no-llm` code path consumed by `run_lap` |
| [src/strategy/eval/](src/strategy/eval/) | `f1-eval` CLI backend — regenerates the model evaluation reports (metrics registry, calibration, threshold hygiene, NLP per-stage eval, headline-number reproduction, LLM-judged alert precision) under `documents/eval_reports/` |
| [src/strategy/inference/tire_predictor.py](src/strategy/inference/tire_predictor.py) | Jupytext-exported tire degradation inference wrapper (N09 era; reference only) |
| [src/strategy/models/lap_time_model.py](src/strategy/models/lap_time_model.py) | Jupytext-exported lap time model module (reference only) |
| [src/strategy/models/tire_degradation_model.py](src/strategy/models/tire_degradation_model.py) | Jupytext-exported tire degradation model module (reference only) |

### `src/telemetry/`

A separate full-stack web application for live telemetry visualisation, independent of the agent notebooks.

| Component | Description |
| ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| [src/telemetry/backend/main.py](src/telemetry/backend/main.py) | FastAPI application entry point; mounts endpoints for telemetry, circuit domination, driver comparison, chat, and voice |
| `src/telemetry/backend/api/` | Versioned API route handlers (`telemetry`, `comparison`, `chatbot`, `voice`) |
| `src/telemetry/backend/services/` | Business logic:`telemetry_service.py`, `comparison_service.py`, and sub-services for telemetry and voice |
| [src/telemetry/frontend/app/main.py](src/telemetry/frontend/app/main.py) | Streamlit multi-page app entry point (dashboard, comparison, chat pages) |
| `src/telemetry/frontend/app/pages/` | Individual Streamlit pages |
| `src/telemetry/frontend/app/components/` | Reusable UI components (auth, layout, navbar) |
| Component | Description |
| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| [src/telemetry/backend/main.py](src/telemetry/backend/main.py) | FastAPI application entry point; mounts endpoints for telemetry, circuit domination, driver comparison, chat, voice, and strategy |
| `src/telemetry/backend/api/` | Versioned API route handlers (`telemetry`, `circuit_domination`, `comparison`, `chat`, `voice`, `strategy` — the last exposes all N25-N31 agents + orchestrator over REST) |
| `src/telemetry/backend/services/` | Business logic: `telemetry/` (FastF1 client + session cache), `chatbot/` (chat engine, LLM service, MCP bridge), `simulation/` (SSE strategy-replay generator), `voice/` (STT/TTS/audio), plus `comparison_service.py` |
| [src/telemetry/frontend/app/main.py](src/telemetry/frontend/app/main.py) | Streamlit multi-page app entry point (dashboard, comparison, chat pages) |
| `src/telemetry/frontend/app/pages/` | Individual Streamlit pages |
| `src/telemetry/frontend/app/components/` | Reusable UI components (auth, layout, navbar) |

### `src/data_extraction/`

Expand Down
Loading
Loading