Files
Guido.Tech/ai_intelligence_layer/RACE_CONTEXT.md
2025-10-18 23:56:53 -05:00

8.5 KiB

Race Context Guide

Why Race Context is Separate from Telemetry

Enrichment Service (port 8000):

  • Provides: Enriched telemetry (changes every lap)
  • Example: tire degradation, aero efficiency, ERS charge

Client/Frontend:

  • Provides: Race context (changes less frequently)
  • Example: driver name, current position, track info, competitors

This separation is intentional:

  • Telemetry changes every lap (real-time HPC data)
  • Race context changes occasionally (position changes, pit stops)
  • Keeps enrichment service simple and focused

How to Call Brainstorm with Both

curl -X POST http://localhost:9000/api/strategy/brainstorm \
  -H "Content-Type: application/json" \
  -d '{
    "enriched_telemetry": [
      {
        "lap": 27,
        "aero_efficiency": 0.85,
        "tire_degradation_index": 0.72,
        "ers_charge": 0.78,
        "fuel_optimization_score": 0.82,
        "driver_consistency": 0.88,
        "weather_impact": "low"
      }
    ],
    "race_context": {
      "race_info": {
        "track_name": "Monaco",
        "current_lap": 27,
        "total_laps": 58,
        "weather_condition": "Dry",
        "track_temp_celsius": 42
      },
      "driver_state": {
        "driver_name": "Hamilton",
        "current_position": 4,
        "current_tire_compound": "medium",
        "tire_age_laps": 14,
        "fuel_remaining_percent": 47
      },
      "competitors": []
    }
  }'

Option 2: AI Layer Fetches Telemetry, Client Provides Context

# Enrichment service POSTs telemetry to webhook
# Then client calls:

curl -X POST http://localhost:9000/api/strategy/brainstorm \
  -H "Content-Type: application/json" \
  -d '{
    "race_context": {
      "race_info": {...},
      "driver_state": {...},
      "competitors": []
    }
  }'

AI layer will use telemetry from:

  1. Buffer (if webhook has pushed data) ← CURRENT SETUP
  2. GET /enriched from enrichment service (fallback)

Creating a Race Context Template

Here's a reusable template:

{
  "race_context": {
    "race_info": {
      "track_name": "Monaco",
      "current_lap": 27,
      "total_laps": 58,
      "weather_condition": "Dry",
      "track_temp_celsius": 42
    },
    "driver_state": {
      "driver_name": "Hamilton",
      "current_position": 4,
      "current_tire_compound": "medium",
      "tire_age_laps": 14,
      "fuel_remaining_percent": 47
    },
    "competitors": [
      {
        "position": 1,
        "driver": "Verstappen",
        "tire_compound": "hard",
        "tire_age_laps": 18,
        "gap_seconds": -12.5
      },
      {
        "position": 2,
        "driver": "Leclerc",
        "tire_compound": "medium",
        "tire_age_laps": 10,
        "gap_seconds": -5.2
      },
      {
        "position": 3,
        "driver": "Norris",
        "tire_compound": "medium",
        "tire_age_laps": 12,
        "gap_seconds": -2.1
      },
      {
        "position": 5,
        "driver": "Sainz",
        "tire_compound": "soft",
        "tire_age_laps": 5,
        "gap_seconds": 3.8
      }
    ]
  }
}

Where Does Race Context Come From?

In a real system, race context typically comes from:

  1. Timing System - Official F1 timing data

    • Current positions
    • Gap times
    • Lap numbers
  2. Team Database - Historical race data

    • Track information
    • Total laps for this race
    • Weather forecasts
  3. Pit Wall - Live observations

    • Competitor tire strategies
    • Weather conditions
    • Track temperature
  4. Telemetry Feed - Some data overlaps

    • Driver's current tires
    • Tire age
    • Fuel remaining
┌─────────────────────┐
│  Timing System      │
│  (Race Control)     │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐         ┌─────────────────────┐
│  Frontend/Client    │         │  Enrichment Service │
│                     │         │  (Port 8000)        │
│  Manages:           │         │                     │
│  - Race context     │         │  Manages:           │
│  - UI state         │         │  - Telemetry        │
│  - User inputs      │         │  - HPC enrichment   │
└──────────┬──────────┘         └──────────┬──────────┘
           │                               │
           │                               │ POST /ingest/enriched
           │                               │ (telemetry only)
           │                               ▼
           │                    ┌─────────────────────┐
           │                    │  AI Layer Buffer    │
           │                    │  (telemetry only)   │
           │                    └─────────────────────┘
           │                               │
           │ POST /api/strategy/brainstorm │
           │ (race_context + telemetry)    │
           └───────────────────────────────┤
                                           │
                                           ▼
                                ┌─────────────────────┐
                                │  AI Strategy Layer  │
                                │  (Port 9000)        │
                                │                     │
                                │  Generates 3        │
                                │  strategies         │
                                └─────────────────────┘

Python Example: Calling with Race Context

import httpx

async def get_race_strategies(race_context: dict):
    """
    Get strategies from AI layer.
    
    Args:
        race_context: Current race state
        
    Returns:
        3 strategies with pit plans and risk assessments
    """
    url = "http://localhost:9000/api/strategy/brainstorm"
    
    payload = {
        "race_context": race_context
        # enriched_telemetry is optional - AI will use buffer or fetch
    }
    
    async with httpx.AsyncClient(timeout=60.0) as client:
        response = await client.post(url, json=payload)
        response.raise_for_status()
        return response.json()

# Usage:
race_context = {
    "race_info": {
        "track_name": "Monaco",
        "current_lap": 27,
        "total_laps": 58,
        "weather_condition": "Dry",
        "track_temp_celsius": 42
    },
    "driver_state": {
        "driver_name": "Hamilton",
        "current_position": 4,
        "current_tire_compound": "medium",
        "tire_age_laps": 14,
        "fuel_remaining_percent": 47
    },
    "competitors": []
}

strategies = await get_race_strategies(race_context)
print(f"Generated {len(strategies['strategies'])} strategies")

Alternative: Enrichment Service Sends Full Payload

If you really want enrichment service to send race context too, you'd need to:

1. Store race context in enrichment service

# In hpcsim/api.py
_race_context = {
    "race_info": {...},
    "driver_state": {...},
    "competitors": []
}

@app.post("/set_race_context")
async def set_race_context(context: Dict[str, Any]):
    """Update race context (call this when race state changes)."""
    global _race_context
    _race_context = context
    return {"status": "ok"}

2. Send both in webhook

# In ingest_telemetry endpoint
if _CALLBACK_URL:
    payload = {
        "enriched_telemetry": [enriched],
        "race_context": _race_context
    }
    await client.post(_CALLBACK_URL, json=payload)

3. Update AI webhook to handle full payload

But this adds complexity. I recommend keeping it simple: client provides race_context when calling brainstorm.


Current Working Setup

Enrichment service → POSTs telemetry to /api/ingest/enriched
AI layer → Stores telemetry in buffer
Client → Calls /api/strategy/brainstorm with race_context
AI layer → Uses buffer telemetry + provided race_context → Generates strategies

This is clean, simple, and follows single responsibility principle!