From 89924c1580cfa6d4902a96c3e76ff11ec292a07a Mon Sep 17 00:00:00 2001 From: Aditya Pulipaka Date: Sun, 19 Oct 2025 05:29:30 -0500 Subject: [PATCH] Remove all previously tracked files that are now ignored --- .gitignore | 1 + ai_intelligence_layer/.env | 25 --------- .../__pycache__/config.cpython-313.pyc | Bin 1819 -> 0 bytes .../__pycache__/main.cpython-312.pyc | Bin 9390 -> 0 bytes .../__pycache__/main.cpython-313.pyc | Bin 27121 -> 0 bytes .../test_api.cpython-312-pytest-8.3.3.pyc | Bin 8539 -> 0 bytes ..._buffer_usage.cpython-312-pytest-8.3.3.pyc | Bin 5072 -> 0 bytes ...st_components.cpython-312-pytest-8.3.3.pyc | Bin 5384 -> 0 bytes ..._webhook_push.cpython-312-pytest-8.3.3.pyc | Bin 5610 -> 0 bytes ...hment_service.cpython-312-pytest-8.3.3.pyc | Bin 8363 -> 0 bytes ai_intelligence_layer/main.py | 36 +++++++++++-- .../__pycache__/input_models.cpython-312.pyc | Bin 6654 -> 0 bytes .../__pycache__/input_models.cpython-313.pyc | Bin 7208 -> 0 bytes .../__pycache__/output_models.cpython-312.pyc | Bin 7184 -> 0 bytes .../__pycache__/output_models.cpython-313.pyc | Bin 7262 -> 0 bytes ai_intelligence_layer/models/input_models.py | 1 + .../analyze_prompt.cpython-313.pyc | Bin 18334 -> 0 bytes .../brainstorm_prompt.cpython-313.pyc | Bin 12644 -> 0 bytes .../prompts/brainstorm_prompt.py | 49 ++++++++++++++---- .../__pycache__/gemini_client.cpython-313.pyc | Bin 6706 -> 0 bytes .../strategy_analyzer.cpython-313.pyc | Bin 5585 -> 0 bytes .../strategy_generator.cpython-313.pyc | Bin 3499 -> 0 bytes .../telemetry_client.cpython-313.pyc | Bin 4949 -> 0 bytes .../services/strategy_generator.py | 10 ++-- ai_intelligence_layer/static/dashboard.html | 38 ++++++++++++-- .../telemetry_buffer.cpython-313.pyc | Bin 3311 -> 0 bytes .../__pycache__/validators.cpython-312.pyc | Bin 11830 -> 0 bytes .../__pycache__/validators.cpython-313.pyc | Bin 5872 -> 0 bytes hpcsim/__pycache__/__init__.cpython-312.pyc | Bin 184 -> 0 bytes hpcsim/__pycache__/__init__.cpython-313.pyc | Bin 180 -> 0 bytes hpcsim/__pycache__/adapter.cpython-312.pyc | Bin 4864 -> 0 bytes hpcsim/__pycache__/adapter.cpython-313.pyc | Bin 4469 -> 0 bytes hpcsim/__pycache__/api.cpython-312.pyc | Bin 4342 -> 0 bytes hpcsim/__pycache__/api.cpython-313.pyc | Bin 4776 -> 0 bytes hpcsim/__pycache__/enrichment.cpython-312.pyc | Bin 14510 -> 0 bytes hpcsim/__pycache__/enrichment.cpython-313.pyc | Bin 12345 -> 0 bytes .../enrich_telemetry.cpython-312.pyc | Bin 2979 -> 0 bytes .../simulate_pi_stream.cpython-312.pyc | Bin 9585 -> 0 bytes .../test_adapter.cpython-312-pytest-8.3.3.pyc | Bin 1805 -> 0 bytes .../__pycache__/test_adapter.cpython-312.pyc | Bin 1692 -> 0 bytes .../test_api.cpython-312-pytest-8.3.3.pyc | Bin 2602 -> 0 bytes tests/__pycache__/test_api.cpython-312.pyc | Bin 2489 -> 0 bytes ...st_enrichment.cpython-312-pytest-8.3.3.pyc | Bin 5620 -> 0 bytes .../test_enrichment.cpython-312.pyc | Bin 2344 -> 0 bytes ...t_integration.cpython-312-pytest-8.3.3.pyc | Bin 6602 -> 0 bytes 45 files changed, 117 insertions(+), 43 deletions(-) delete mode 100644 ai_intelligence_layer/.env delete mode 100644 ai_intelligence_layer/__pycache__/config.cpython-313.pyc delete mode 100644 ai_intelligence_layer/__pycache__/main.cpython-312.pyc delete mode 100644 ai_intelligence_layer/__pycache__/main.cpython-313.pyc delete mode 100644 ai_intelligence_layer/__pycache__/test_api.cpython-312-pytest-8.3.3.pyc delete mode 100644 ai_intelligence_layer/__pycache__/test_buffer_usage.cpython-312-pytest-8.3.3.pyc delete mode 100644 ai_intelligence_layer/__pycache__/test_components.cpython-312-pytest-8.3.3.pyc delete mode 100644 ai_intelligence_layer/__pycache__/test_webhook_push.cpython-312-pytest-8.3.3.pyc delete mode 100644 ai_intelligence_layer/__pycache__/test_with_enrichment_service.cpython-312-pytest-8.3.3.pyc delete mode 100644 ai_intelligence_layer/models/__pycache__/input_models.cpython-312.pyc delete mode 100644 ai_intelligence_layer/models/__pycache__/input_models.cpython-313.pyc delete mode 100644 ai_intelligence_layer/models/__pycache__/output_models.cpython-312.pyc delete mode 100644 ai_intelligence_layer/models/__pycache__/output_models.cpython-313.pyc delete mode 100644 ai_intelligence_layer/prompts/__pycache__/analyze_prompt.cpython-313.pyc delete mode 100644 ai_intelligence_layer/prompts/__pycache__/brainstorm_prompt.cpython-313.pyc delete mode 100644 ai_intelligence_layer/services/__pycache__/gemini_client.cpython-313.pyc delete mode 100644 ai_intelligence_layer/services/__pycache__/strategy_analyzer.cpython-313.pyc delete mode 100644 ai_intelligence_layer/services/__pycache__/strategy_generator.cpython-313.pyc delete mode 100644 ai_intelligence_layer/services/__pycache__/telemetry_client.cpython-313.pyc delete mode 100644 ai_intelligence_layer/utils/__pycache__/telemetry_buffer.cpython-313.pyc delete mode 100644 ai_intelligence_layer/utils/__pycache__/validators.cpython-312.pyc delete mode 100644 ai_intelligence_layer/utils/__pycache__/validators.cpython-313.pyc delete mode 100644 hpcsim/__pycache__/__init__.cpython-312.pyc delete mode 100644 hpcsim/__pycache__/__init__.cpython-313.pyc delete mode 100644 hpcsim/__pycache__/adapter.cpython-312.pyc delete mode 100644 hpcsim/__pycache__/adapter.cpython-313.pyc delete mode 100644 hpcsim/__pycache__/api.cpython-312.pyc delete mode 100644 hpcsim/__pycache__/api.cpython-313.pyc delete mode 100644 hpcsim/__pycache__/enrichment.cpython-312.pyc delete mode 100644 hpcsim/__pycache__/enrichment.cpython-313.pyc delete mode 100644 scripts/__pycache__/enrich_telemetry.cpython-312.pyc delete mode 100644 scripts/__pycache__/simulate_pi_stream.cpython-312.pyc delete mode 100644 tests/__pycache__/test_adapter.cpython-312-pytest-8.3.3.pyc delete mode 100644 tests/__pycache__/test_adapter.cpython-312.pyc delete mode 100644 tests/__pycache__/test_api.cpython-312-pytest-8.3.3.pyc delete mode 100644 tests/__pycache__/test_api.cpython-312.pyc delete mode 100644 tests/__pycache__/test_enrichment.cpython-312-pytest-8.3.3.pyc delete mode 100644 tests/__pycache__/test_enrichment.cpython-312.pyc delete mode 100644 tests/__pycache__/test_integration.cpython-312-pytest-8.3.3.pyc diff --git a/.gitignore b/.gitignore index ee79715..9204635 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env +__pycache__/ *.pyc \ No newline at end of file diff --git a/ai_intelligence_layer/.env b/ai_intelligence_layer/.env deleted file mode 100644 index 4603b93..0000000 --- a/ai_intelligence_layer/.env +++ /dev/null @@ -1,25 +0,0 @@ -# Gemini API Configuration -GEMINI_API_KEY=AIzaSyDK_jxVlJUpzyxuiGcopSFkiqMAUD3-w0I -GEMINI_MODEL=gemini-2.5-flash - -# Service Configuration -AI_SERVICE_PORT=9000 -AI_SERVICE_HOST=0.0.0.0 - -# Enrichment Service Integration -ENRICHMENT_SERVICE_URL=http://localhost:8000 -ENRICHMENT_FETCH_LIMIT=10 - -# Demo Mode (enables caching and consistent responses for demos) -DEMO_MODE=false - -# Fast Mode (use shorter prompts for faster responses) -FAST_MODE=true - -# Strategy Generation Settings -STRATEGY_COUNT=3 # Number of strategies to generate (3 for testing, 20 for production) - -# Performance Settings -BRAINSTORM_TIMEOUT=90 -ANALYZE_TIMEOUT=120 -GEMINI_MAX_RETRIES=3 diff --git a/ai_intelligence_layer/__pycache__/config.cpython-313.pyc b/ai_intelligence_layer/__pycache__/config.cpython-313.pyc deleted file mode 100644 index 4d2f9ebce8940f4a20227e83467a9317c7bae12f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1819 zcmZuy&2Jk;6rZ)%>$T%J-*Jf3W}6QY1F-`lqKzt0XjNz%B}faWT8uX9u`{sVb>5Dn z+Tvh|135-Qk$UBX_-|VIVpipVIOP^d5Le#J+NG5kYu~)zd-L(;z2A(l#>cY++t2Om zqtg^2e@HNDh*i7#8oP6{PHY0i*6hS%?NI^}kCKqIBu+loAEh8=kp;3sY<-c~scK?7 z8BYeoHjdNPRMn8nRZTnnHuknzH9kz(nMLxA4w;5g%65;l_X5Ap8*Oj|4}7cX_)dd0 znJ=t*0M_n9>!B~0=kW&fU1se$9R}s>S0M|nR;T9pg1eg`6N3AVP|aZe35UQ}E1WpM zokNdVCyvK!YJ+n2LPl6hM7d9$klDkj(ey}*!@190QPLvwpe3VnJXcN{we(QAdXCCD zsS?mIM+sYlBxWlCx;(d?R43L!Wx-A_t0o7wx4xI?UNO zV7_s)v>chETwG*uVE3clR?FjVT%T9D_5!EIYE~VBruBb056e*=3(0*>offCxvQBr1 zH{UOBZ?+(aazlSJs4W4bM>!itgNz5Urg`#S2`= zla`&^TU%SvJoACON3#B}R%(NHAqoG6v(AKjL_OZ*;z5+Dv1UMJAYVqAx)TbeUr07b z`A{G^S))VUpzVu`o69UbEnjW3fc}jr^;4JLw zWlUK&)fV;5+mXQ=egLebM@_0vDAe9xy_;z`@z$WQG|12YnMutW-|xXYqnP(2b9BWb1L@KR|BbgNfdeHgueMN} zlP4(S=3>2`NRMjU!~XcS5o@HRb*;~su<&7Zfgz`@(O#D1vV$*dxs-tSaB`eQS(iAr zcTtlUR$i+3wS@|rKEN-WN6{nK1~DgJqzf-+ia+k0nlHy@dIxH5DGRG|_SERX{%;8x zZ%h+IbXv%Akbf8P-YSZ93FStLBCmyF-i>MgF~|@!{6cyCE|Z$3{gp^+`adSoKKYFl quZ diff --git a/ai_intelligence_layer/__pycache__/main.cpython-312.pyc b/ai_intelligence_layer/__pycache__/main.cpython-312.pyc deleted file mode 100644 index 135fba68b4c0d3d159109e144c6b852fd2868078..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9390 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 diff --git a/ai_intelligence_layer/__pycache__/main.cpython-313.pyc b/ai_intelligence_layer/__pycache__/main.cpython-313.pyc deleted file mode 100644 index 2f3e0ffb7a54130bead52b8fdc2495d6185b775e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27121 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 qvhJC)ldOF) diff --git a/ai_intelligence_layer/__pycache__/test_buffer_usage.cpython-312-pytest-8.3.3.pyc b/ai_intelligence_layer/__pycache__/test_buffer_usage.cpython-312-pytest-8.3.3.pyc deleted file mode 100644 index 2da09605a1329743df31aa17bf61e6587041349d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5072 zcmbVQTWlN06`duQ?`@E8!TzFu-JPy-`R z1o%%sxJCj$V-#0+ohtGulr$s_o!e6Xv7but;W<{pvcf7Ndk#zdbdptOF*`8I3ZW#H z*o2H_b}BJFjU~*1q=2JXk&^7RBu3eJJT)tdbF$AqIm^qM9(cp_uo#UCSix*OAsCQlnsXj z0i2oVm02+Xo^Ln>Q!D&sLkUHUh7_L2C++Jb`teSKYDq|f7{@WyavHypfY^a%J#%_& zSdv6ZwH=w9JgIe4J+q1u@Avx!5j4z-veN(ky?giiLvh|OD^f_oGfDr{hFdBlg~B)( z7GnxtP*n4AF%}Ao>rG&Fy&qnxaY#z8?}1*YNwvfL@LVt!iel9fPDm1tDM29=2ZpGG z1k#mN_dE_kHYK8y;}u?vsh;9I1xMq-FcxG!A*8|?N#gc;-XyCTB}nOULp}h<6ZTJ|2ue5#3&F=`f^jT` z!R=0?YSSX;W7DF_lq|^#elyurN~tsviWoLzHaZH4 zOMCPZj#zX`x#cLGyNDE~E>en9m*vd51`1VBEzhJ{ z%Tyaus&pM`inD!Wzg~*s1+-{L8zOFuPN^j<|I#)`~%b$+=`8+9)hY0j}| zQnu;5w25OXyf9bjsn=!7ZJJJ-Ip;^N>ts#ffdi_F{OKAt<)d1+xryplNTq8}nvQJO z`{kDN%phH#uHiBqa_?`%ut}dcZMux!H|UZS+DfY~A$?J?X0`zsP;&A~W0l7~75m}6N z8dA(4xwK`7jc*^tr?P&Y2Ksx{7Q z7)(xCN&>2TO5*W!ki&9V;^U-b624MSCe92F4o^(G|nS)q3teONd#K|hHfpeNDR*eGSbmI(GR2z;ZqFS+m zWs#3b031PqHqi`fpoAr|;;LfQ+R>UP zC;ew&Wo7?dNP=yhn8HbaToNOYP}x5l56gTMAUO7i_#os23j#kwDirWGe0%xHcUiFb z?G;SOfWv+9q}o)ZZhUqG$#GMXl1_vDHsZ*?VUd>5zZ_NX_P^c#Ya!=oyXV+**Rf~i z#hl~0rJ*&ud(B$6>U7_4_N~@+JTMvE_JS2v*FCDTI?PLhkG#la&)N^>>6h1NTh{)A zJbh5>4Cd*f0^Mz@U2}SuCo-*h=dJ>3wAHV8SDV=nM&BE~eC%Gc?{2eiWj@#Z;`!ri zwG9^o7Xle)uGV*cq+mu(2hJZ`bJs47g}*Z`vlHA0#Z!x(9rjvF2!R6A}U+Q(O3{P@6!2R^a>nfU{AGnjq# zN4foHb6tV#o*!o$U(0)62cc|p?~RV%cmJ;Ylhm!gT;F)M_e8ewWZrvUKpWVL47;}>Anw55B@K(Zf@g?RGVsT03_v>!3G50M2{+Ui`c%23zLSIw6eGSW)R z#~mMbtTbj_&*!Z#6b!V@z1q+@!pP=ZMlZt^GC^o9Lv}*rL&&y&zYY8 z77Ucl{RLC~WUb2k?V6+JAu?#Hv(@dHH?A#QUC2bTuHL-0ugLd4M0A;-31?k<^46{| zt@W!`_dRRVU29X`x}As?Y#{eUUV@_kw8c4Eg+BES7)Oo9zw|a7*=PEzeYgzLqx+4w5B41GHr(l=pns>^aCEQf zj?YB;`x%h=jIKY{V*IQ{>-V&dd5wSfnt-lagF*6b91Kcb;7(_)Y6%88F&qr4)~N)1 zp~LSND)UM_3A?p4Y6!-YWIy{tG8_}+%<@TiUV;CoghV5SPhs5a6OwPRgo9yWV9ugYg2d ze2Ad7LGl#5o>&jS&o~JIAC$r{B-ggQ46lNbqNoS7iJ~7fh@##?KXZJAy1qi)_ua27 zx!_DO)!c7vU2WRF+St6>(!Scd^MS)$XD?Kv=Jr*#Wp!82>h>M0?HxdEuoqmYzVX41 z>RNNb=&3d=F%LU_K-CuBq!7)VPyNH#@Fnf~!qu5`buArUrJ1F{UmW@Akqf)uK6UAh P&*_$e1<{St6gc%igXk}H diff --git a/ai_intelligence_layer/__pycache__/test_components.cpython-312-pytest-8.3.3.pyc b/ai_intelligence_layer/__pycache__/test_components.cpython-312-pytest-8.3.3.pyc deleted file mode 100644 index 523b9f3d6807806318097414b11c82bdfd4403b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5384 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 MM!Vdfb&>YJ0r~=+w*UYD diff --git a/ai_intelligence_layer/__pycache__/test_webhook_push.cpython-312-pytest-8.3.3.pyc b/ai_intelligence_layer/__pycache__/test_webhook_push.cpython-312-pytest-8.3.3.pyc deleted file mode 100644 index 1b75c7b2e42eb16a658af9eded6488d56d63e4c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5610 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 a==(?LcL3#)_()&b_crv diff --git a/ai_intelligence_layer/main.py b/ai_intelligence_layer/main.py index f2fe67a..8140916 100644 --- a/ai_intelligence_layer/main.py +++ b/ai_intelligence_layer/main.py @@ -49,6 +49,7 @@ strategy_generator: StrategyGenerator = None telemetry_client: TelemetryClient = None current_race_context: RaceContext = None # Store race context globally last_control_command: Dict[str, int] = {"brake_bias": 5, "differential_slip": 5} # Store last command +strategy_history: List[Dict[str, Any]] = [] # Track past strategies for continuity # WebSocket connection manager class ConnectionManager: @@ -378,7 +379,7 @@ async def websocket_pi_endpoint(websocket: WebSocket): 2. AI layer processes telemetry and generates strategies 3. AI layer pushes control commands back to Pi (brake_bias, differential_slip) """ - global current_race_context, last_control_command + global current_race_context, last_control_command, strategy_history vehicle_id = await websocket_manager.connect(websocket) @@ -389,7 +390,11 @@ async def websocket_pi_endpoint(websocket: WebSocket): # Reset last control command to neutral for new session last_control_command = {"brake_bias": 5, "differential_slip": 5} + # Clear strategy history for new race + strategy_history = [] + logger.info("[WebSocket] Telemetry buffer cleared for new connection") + logger.info("[WebSocket] Strategy history cleared for new race") # Notify dashboards of new vehicle connection await dashboard_manager.broadcast({ @@ -454,12 +459,26 @@ async def websocket_pi_endpoint(websocket: WebSocket): try: response = await strategy_generator.generate( enriched_telemetry=buffer_data, - race_context=current_race_context + race_context=current_race_context, + strategy_history=strategy_history ) # Extract top strategy (first one) top_strategy = response.strategies[0] if response.strategies else None + # Add to strategy history + if top_strategy: + strategy_history.append({ + "lap": lap_number, + "strategy_name": top_strategy.strategy_name, + "risk_level": top_strategy.risk_level, + "brief_description": top_strategy.brief_description, + "reasoning": top_strategy.reasoning + }) + # Keep only last 10 strategies + if len(strategy_history) > 10: + strategy_history.pop(0) + # Generate control commands based on strategy control_command = generate_control_command( lap_number=lap_number, @@ -490,6 +509,11 @@ async def websocket_pi_endpoint(websocket: WebSocket): "type": "lap_data", "vehicle_id": vehicle_id, "lap_data": enriched, + "race_context": { + "position": current_race_context.driver_state.current_position, + "gap_to_leader": current_race_context.driver_state.gap_to_leader, + "gap_to_ahead": current_race_context.driver_state.gap_to_ahead + }, "control_output": { "brake_bias": control_command["brake_bias"], "differential_slip": control_command["differential_slip"] @@ -497,7 +521,8 @@ async def websocket_pi_endpoint(websocket: WebSocket): "strategy": { "strategy_name": top_strategy.strategy_name, "risk_level": top_strategy.risk_level, - "brief_description": top_strategy.brief_description + "brief_description": top_strategy.brief_description, + "reasoning": top_strategy.reasoning } if top_strategy else None, "timestamp": datetime.now().isoformat() }) @@ -527,6 +552,11 @@ async def websocket_pi_endpoint(websocket: WebSocket): "type": "lap_data", "vehicle_id": vehicle_id, "lap_data": enriched, + "race_context": { + "position": current_race_context.driver_state.current_position, + "gap_to_leader": current_race_context.driver_state.gap_to_leader, + "gap_to_ahead": current_race_context.driver_state.gap_to_ahead + }, "control_output": { "brake_bias": 5, "differential_slip": 5 diff --git a/ai_intelligence_layer/models/__pycache__/input_models.cpython-312.pyc b/ai_intelligence_layer/models/__pycache__/input_models.cpython-312.pyc deleted file mode 100644 index eb48bff94e24e2dc3c59aa01c9d107fe2e43a2c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6654 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 PMiP0er~XA{6ukcffHZYH diff --git a/ai_intelligence_layer/models/__pycache__/output_models.cpython-312.pyc b/ai_intelligence_layer/models/__pycache__/output_models.cpython-312.pyc deleted file mode 100644 index d1a961497c9548d9fcbbacf8a2ca1a054d33e5ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7184 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 E1n2kNO#lD@ diff --git a/ai_intelligence_layer/prompts/brainstorm_prompt.py b/ai_intelligence_layer/prompts/brainstorm_prompt.py index d1c4ae9..a9ad13b 100644 --- a/ai_intelligence_layer/prompts/brainstorm_prompt.py +++ b/ai_intelligence_layer/prompts/brainstorm_prompt.py @@ -9,7 +9,8 @@ from config import get_settings def build_brainstorm_prompt_fast( enriched_telemetry: List[EnrichedTelemetryWebhook], - race_context: RaceContext + race_context: RaceContext, + strategy_history: List[dict] = None ) -> str: """Build a faster, more concise prompt for quicker responses (lap-level data).""" settings = get_settings() @@ -27,17 +28,29 @@ def build_brainstorm_prompt_fast( if gap_to_leader > 0 and position > 1: comp_info += f", {gap_to_leader:.1f}s from leader" + # Format strategy history (last 3 strategies) + history_text = "" + if strategy_history and len(strategy_history) > 0: + recent_history = strategy_history[-3:] # Last 3 strategies + history_lines = [] + for h in recent_history: + history_lines.append(f"Lap {h['lap']}: {h['strategy_name']} (Risk: {h['risk_level']})") + history_text = f"\n\nPAST STRATEGIES:\n" + "\n".join(history_lines) + history_text += f"\n\nREQUIREMENT: If changing from previous strategy '{recent_history[-1]['strategy_name']}', explain WHY the switch is necessary. If staying with same approach, explain continuity." + else: + history_text = "\n\nNOTE: This is the first strategy generation - no previous strategy to compare." + if count == 1: # Ultra-fast mode: just generate 1 strategy return f"""Generate 1 F1 race strategy for {race_context.driver_state.driver_name} at {race_context.race_info.track_name}. CURRENT: Lap {race_context.race_info.current_lap}/{race_context.race_info.total_laps}, {comp_info}, {race_context.driver_state.current_tire_compound} tires ({race_context.driver_state.tire_age_laps} laps old) -TELEMETRY: Tire deg {latest.tire_degradation_rate:.2f}, Cliff risk {latest.tire_cliff_risk:.2f}, Pace {latest.pace_trend}, Position trend {latest.position_trend}, Competitive pressure {latest.competitive_pressure:.2f} +TELEMETRY: Tire deg {latest.tire_degradation_rate:.2f}, Cliff risk {latest.tire_cliff_risk:.2f}, Pace {latest.pace_trend}, Position trend {latest.position_trend}, Competitive pressure {latest.competitive_pressure:.2f}{history_text} Generate 1 optimal strategy considering competitive position. Min 2 tire compounds required. -JSON: {{"strategies": [{{"strategy_id": 1, "strategy_name": "name", "stop_count": 1, "pit_laps": [32], "tire_sequence": ["medium", "hard"], "brief_description": "one sentence", "risk_level": "medium", "key_assumption": "main assumption"}}]}}""" +JSON: {{"strategies": [{{"strategy_id": 1, "strategy_name": "name", "stop_count": 1, "pit_laps": [32], "tire_sequence": ["medium", "hard"], "brief_description": "one sentence", "reasoning": "detailed explanation including strategy change rationale if applicable", "risk_level": "medium", "key_assumption": "main assumption"}}]}}""" elif count <= 5: # Fast mode: 2-5 strategies with different approaches @@ -47,11 +60,13 @@ CURRENT: Lap {race_context.race_info.current_lap}/{race_context.race_info.total_ TELEMETRY: Tire deg {latest.tire_degradation_rate:.2f}, Cliff risk {latest.tire_cliff_risk:.2f}, Pace {latest.pace_trend}, Delta {latest.performance_delta:+.2f}s, Position trend {latest.position_trend}, Competitive pressure {latest.competitive_pressure:.2f} -COMPETITIVE SITUATION: Gap to ahead {gap_to_ahead:.1f}s ({"DRS RANGE - attack opportunity!" if gap_to_ahead < 1.0 else "close battle" if gap_to_ahead < 3.0 else "need to push"}) +COMPETITIVE SITUATION: Gap to ahead {gap_to_ahead:.1f}s ({"DRS RANGE - attack opportunity!" if gap_to_ahead < 1.0 else "close battle" if gap_to_ahead < 3.0 else "need to push"}){history_text} Generate {count} strategies balancing tire management with competitive pressure. Consider if aggressive undercut makes sense given gaps. Min 2 tire compounds each. -JSON: {{"strategies": [{{"strategy_id": 1, "strategy_name": "Conservative Stay Out", "stop_count": 1, "pit_laps": [35], "tire_sequence": ["medium", "hard"], "brief_description": "extend current stint then hard tires to end", "risk_level": "low", "key_assumption": "tire cliff risk stays below 0.7"}}]}}""" +CRITICAL: Each strategy MUST include 'reasoning' field explaining the approach and, if applicable, why it differs from or continues the previous strategy. + +JSON: {{"strategies": [{{"strategy_id": 1, "strategy_name": "Conservative Stay Out", "stop_count": 1, "pit_laps": [35], "tire_sequence": ["medium", "hard"], "brief_description": "extend current stint then hard tires to end", "reasoning": "Detailed explanation of this strategy including why we're switching from/continuing previous approach based on current telemetry and competitive situation", "risk_level": "low", "key_assumption": "tire cliff risk stays below 0.7"}}]}}""" return f"""Generate {count} F1 race strategies for {race_context.driver_state.driver_name} at {race_context.race_info.track_name}. @@ -59,16 +74,19 @@ CURRENT: Lap {race_context.race_info.current_lap}/{race_context.race_info.total_ TELEMETRY: Tire deg {latest.tire_degradation_rate:.2f}, Cliff risk {latest.tire_cliff_risk:.2f}, Pace {latest.pace_trend}, Delta {latest.performance_delta:+.2f}s, Position trend {latest.position_trend}, Competitive pressure {latest.competitive_pressure:.2f} -COMPETITIVE: Gap ahead {gap_to_ahead:.1f}s, Position trending {latest.position_trend} +COMPETITIVE: Gap ahead {gap_to_ahead:.1f}s, Position trending {latest.position_trend}{history_text} Generate {count} diverse strategies considering both tire management AND competitive positioning. Min 2 compounds. -JSON: {{"strategies": [{{"strategy_id": 1, "strategy_name": "name", "stop_count": 1, "pit_laps": [32], "tire_sequence": ["medium", "hard"], "brief_description": "one sentence", "risk_level": "low|medium|high|critical", "key_assumption": "main assumption"}}]}}""" +CRITICAL: Each strategy MUST include 'reasoning' field with detailed rationale and strategy continuity/change explanation. + +JSON: {{"strategies": [{{"strategy_id": 1, "strategy_name": "name", "stop_count": 1, "pit_laps": [32], "tire_sequence": ["medium", "hard"], "brief_description": "one sentence", "reasoning": "Comprehensive explanation including strategy evolution context", "risk_level": "low|medium|high|critical", "key_assumption": "main assumption"}}]}}""" def build_brainstorm_prompt( enriched_telemetry: List[EnrichedTelemetryWebhook], - race_context: RaceContext + race_context: RaceContext, + strategy_history: List[dict] = None ) -> str: """ Build the brainstorm prompt for Gemini. @@ -76,6 +94,7 @@ def build_brainstorm_prompt( Args: enriched_telemetry: Recent enriched telemetry data race_context: Current race context + strategy_history: List of previous strategies for context Returns: Formatted prompt string @@ -108,6 +127,14 @@ def build_brainstorm_prompt( "gap_seconds": round(c.gap_seconds, 1) }) + # Format strategy history + history_section = "" + if strategy_history and len(strategy_history) > 0: + history_section = "\n\nSTRATEGY HISTORY (Recent decisions):\n" + for h in strategy_history[-5:]: # Last 5 strategies + history_section += f"- Lap {h['lap']}: {h['strategy_name']} (Risk: {h['risk_level']}) - {h.get('brief_description', 'N/A')}\n" + history_section += f"\nCONTEXT: Previous strategy was '{strategy_history[-1]['strategy_name']}'. If recommending a change, clearly explain WHY. If continuing same approach, explain the continuity.\n" + prompt = f"""You are an expert F1 strategist. Generate 20 diverse race strategies based on lap-level telemetry AND competitive positioning. LAP-LEVEL TELEMETRY METRICS: @@ -135,7 +162,7 @@ COMPETITORS: {competitors_data} ENRICHED TELEMETRY (Last {len(telemetry_data)} laps, newest first): -{telemetry_data} +{telemetry_data}{history_section} KEY INSIGHTS: - Latest tire degradation rate: {latest.tire_degradation_rate:.3f} @@ -160,9 +187,12 @@ For each strategy provide: - pit_laps: [array of lap numbers] - tire_sequence: [array of compounds: "soft", "medium", "hard"] - brief_description: One sentence rationale +- reasoning: DETAILED explanation (3-5 sentences) including: (1) Why this strategy fits current conditions, (2) How it addresses telemetry trends, (3) Strategy evolution - why changing from or continuing previous approach - risk_level: "low", "medium", "high", or "critical" - key_assumption: Main assumption this strategy relies on +CRITICAL: The 'reasoning' field must include strategy continuity/change rationale relative to past decisions. + OUTPUT FORMAT (JSON only, no markdown): {{ "strategies": [ @@ -173,6 +203,7 @@ OUTPUT FORMAT (JSON only, no markdown): "pit_laps": [32], "tire_sequence": ["medium", "hard"], "brief_description": "Extend mediums to lap 32, safe finish on hards", + "reasoning": "Current tire degradation at 0.45 suggests we can safely extend to lap 32 before hitting the cliff. This maintains our conservative approach from lap 3 as conditions haven't changed significantly - tire deg is stable and we're not under immediate competitive pressure. The hard tire finish provides low-risk race completion.", "risk_level": "low", "key_assumption": "Tire degradation stays below 0.85 until lap 32" }} diff --git a/ai_intelligence_layer/services/__pycache__/gemini_client.cpython-313.pyc b/ai_intelligence_layer/services/__pycache__/gemini_client.cpython-313.pyc deleted file mode 100644 index 13195d89a2a4a25041e6ac2f5ed47cf83511e86b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6706 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 GxcwhG4i}~X diff --git a/ai_intelligence_layer/services/__pycache__/strategy_analyzer.cpython-313.pyc b/ai_intelligence_layer/services/__pycache__/strategy_analyzer.cpython-313.pyc deleted file mode 100644 index 5c7b2fef2c6b395a5430b17e4231ab482f9903fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5585 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 QY*~tOeGNZkQB_<156pUc1poj5 diff --git a/ai_intelligence_layer/services/__pycache__/strategy_generator.cpython-313.pyc b/ai_intelligence_layer/services/__pycache__/strategy_generator.cpython-313.pyc deleted file mode 100644 index 36adeca42098645fb6ca91cce537d172fe121ac5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3499 zcmai1U2Gf25#A$@$K&x=6!l|DmQFvZLo_0-zc^+h>(@?1#&W?c(;`xHIFn22Tjtsa!`_S3r9m&`= zx)AqfcV>5IXTF(Podkmdf)@JClWmtDp?}bU(^#80`2vVrNJ0cjjO5BPgn_R+>&m!^ zTcmSrmd$vG$D%!1F5@NM3{UuskNB)PE-PgG#Bb5wY##WDv!`7{JyOZgcRWM%2PK zF8&Z#@D4V}?vL=*?P~R>raz|?@M={v@CSy;JBPy-(asq;tk|KipGpR#=2NkuVbQP zk-%j|y=7q)=Ic5bNNn9nTwYHWY!6wwxuK`OlWWl3LYr;gyv0T+k1FlCO{%2Ty0~<; z)i!yD$^lBBZ4%=kLqvcAcVlE-QwiR0W5zIM0#XZDt|+^hq-?C}Dcj1savR6V+OEmVut+sz*^E1PXnQT` z@OnW7eH^+E(Kn|PpTD=q-s9sB1}8rc?XkZKKHx(){Wtv0*xXfO^|4{?s+(g0{xkm zqvm_2=%8llM!(^UNgT(Z)w(XtUp$_aX&kG@(ng z(+;omm4v(yLbEPMClQT;T{U4@xO@}rY*8hqgcjVRsKlIemzYGjaUwX0OPo3TqSTcX zgk@6J(}D=?dHAQr945SYkrXiXHo`=gWfl zzG`e!RXd5*UZ@e?4gv8sxI$Ti`YEXQd&fUBW4~8rF)Y_kD$EV0c1nli6#j3vUp)b7w-cS0X@YvLG~;Nt||; z3N)O1qMI+`GNnH2hpMC@bW=)r5RXx7(esdzwgIjaIwK<=E2a!{?OFz5_BK)_apJc$k={l?DorljeP&H7Y%&xNyxs= z$Jf5-z5VX5N1Nhwb9$v2TfN7xJ>k&s)Zx(5-JzvF#1DqvZSsRK6&Y_%E$oLcH2DjU z&w*P10+Yl}pCE=F7wP{r^hu~W_WGC0U(Pm17Y`##cOy&xK6X>?fAj?~kmaA%m5R*?%W_F2x=~RztW|;SmE~f!Aj^a%UP5a!p%sSE3TuIq z%m8Kf$p9e5Pz$nR7(~5VH?R(ipn4!ONIME45_CEmF#0rfzeHcNZ+y$Lo>z|p=RAuK zhsEaD`TgPau?I%rqJi;aFQs@S3_tY&)!L12l;|g~!N>H{R}=(~$r-yf8bnk{lY<0W zQp>F;S1%3aik?)pTD=w56}{^kRxHMB8OTLlLNx5me&wvk(3ic-wmDkvS@BB^=8V-?fg(ztM8a1+oHi5JN~`g%0q*Fppg>hCSgB z6Fx!%M`-l#=*m92a)f4&Q0fRR9HHbxU*ymizw3*C_S%7O@{eyO_hb<6W=YhC_L`0B?McYYCu<^DL z8@!p5%n6pTCpf|hbe=uQpRg0VL31Y^C!EA7pb6V(ou#()-i0RI-Pr6Ck00$qA|F7a zz1vn8tC+Hd9N81DF)1z0NE(?Jl4)5|G$EBCLQ2w-)3P!pND7gY)6%3cna~nKiezSl zp_ihC;Tg)VO5{yBDeZIJql!mDHk~~stD5e3aaNNvN+KP?x@St#;;N)+pi+gtf3Tpo zxcIBm+38H?^`yBuv*in&tq~xupa}%NLDVmV5p9GOnE)c3=n}aJe!|WHkH}9rCY+Qy z$cpv=I>(;F#08`7gErAY`@|zUNyQW!a_g1FwWEgJ_bNaxd(`Ya!3kQ?SB57{=WO#r zvfy&ig%CYt27X)Dp}B&_i*w!3r;mbTc(iaJ=7`zGP`Wq@9F`->Sb)O{AvA7;8J!%Z zHazl(IEF@xyroGmI$*N`L_iP>OtxuQku^Dyma~#jGSv)=ec6_x!>mY=i|mtz!$v}O zLcOmylsp5+Zp24?j-++R*@P+?R5^zcZ1J=_BWt?5yu+t6Q&SSrSy@SCXke*QI;A_T zKvJoX1VJAQ$6ygPoS2kn=fVS-NZA&d%$OIEctvJg)nThMU2$&zh-%_0{K~c?W$}+x)@v3yuxHkoWhl`Fj`G zUsP-aTl2xbwP4=@yYBFBI=t_@FS>ILy-VyT6(3hDzMZQ({#VD)7RaL!oipv{iKNXD zC0RUvm~_JLJ@{>X2Eo*d1PG-VPI?f6gN5No9|$V+xS;YP(RRS5*hD6VJF&v-MB~M< z7_~pD1->RWW&;^6hN0yTaHU`wcUat`#n7`x5Y04p(eW(CXc%(YH0=3Je1#d|JV;?< z?Bhc8OsnX8);0_oZW}ij<3=k>dM(QOcmxFV)z)a~ZOtqE57_4#ueGFNyk#BO>OR0& zJy?UUMX%UZTNtUfS~TQ^kJdh3Z^?<(ohW7>z&-dS+i3^~H=K^*Q0y^>O7l1TS^0Jt z`sLOMs0}&L$j{;TrfL&FyJAn#5pN561{vINI;Q6w$b;GoOHM)(NdbQ|tOTDeKEgDk z6mCIfXVPHpuJpE}ga|u#mU*PHG;2|!C*~XtSiRDFw5dc})b{i--fWGF75|?O34EnE zBhC~qvqZ48mfm0q9PkfX;*B|6s*S>$bqMW-Jx6pL znlcZd?S+r9Zr9`)DKn=5hTvxtBr&6A9flIvUbd!8O~G^7=Ap5%mjsEBa!^xTtxw3d z4jNFTyokfTX$}UJh8!^M8ZB7zUlg@R6N-}2sACl=sZk$)|HOoZCS;$ADbo2_;IURH z!L72LeS|{Q1kw#6km(VjiIC8OqjS@mHhW%oN7Q*GX;vhi0f41f5qc7Fz;AI?OK5Yd z&Yn{W<4hE>&Ke&v`=&%tlS) zweDPX%L0F&ZE)6XdTQQ3dGTZ}uz&Hu;!}&~m${|4mJ>Pu(7I>%D_>LI*M7&>zF3#{ z_1y9GEbZQCdHT13Uj=SNuLp81NAtm>mmC{a{(Mzvttzx$)$ygT`Raws7e09V61!Q| zaMgX;eQo;J>WzaR&R>5$*A>k*4XjrUe$7J}JdN)LPXC2nX4iuU)`Eu@C)b0A|IA*p z=K`lUd^;c1B7ZNedDqwTdGP4Jzwx5r2!2p)4#IfO*Yoh(22@p_uWVbZY}-OM=LDvv zoVs`_7wlW=`lRpUzWm{r*ABm&>l@8AitC=S&6;3tXJonM_MVkJ`TjF&{bzEKALW{U ze79yi=NW&vSy`8_Y+0*pp~}vblpR@0EQz_s$hxQB&~R*7yM1Bh!g40p^vd0uS96|M zLDWx$3||@>cwxDEnaMQ{ta}DGJk<~Hb1?ax`bRjZcUzC|!oN8<;6^I}9No>Y1Q|;2 ztc`XtD_uC+&ado`xS(_Mx%%iHezlqbdbQ32OsfKphWXVNmeNmQ(6hQ5Q@R~fo;@6G z!^TJ#Kj5&h_Tp%tXZ4T==vypZ=9ZmG-EtVTyY6^1bE`Sx9o)AJBf9-q%_5$>P0b}9uB7S=u^ag|kD6D{x z*m6{$*kZQFVX+vt5DB29?Gj9k87<;5*k$1nxxOLzRBR$k|H@FvHt7NiIRdz2H~gFh z?7>d|FW7@EVviyUgc`XEY9u>ObC&Tu4#A0hjNM+Ho53oDjj&U8^PR%mYNaD9xuVlj z@^wMB>e04@Evt~T6Uphs*)&{4x0kUoGAB{70@xRTcUnrMwdwh1gky=cDhU~FS|V>j z>U3r8VRNofbLw6oL9k-v-e=He>xT?E0q(=F6I#@y$v)v&$YEw^3W10~n-G z{{s&Bdw}(>ulw_0=L5#Wi>(%|4rVYov!|F=4P$GzmvJy!O`(f zj*fIQK!{%v8qXDVeBRT2>?_ z1Jm|+d@_@a#|i!S3!!%@oq<~>fg2Ap>MiM_W9->XCQW)MSsynlvz&}4G>yn-=K%PD zJcXEqqITol3H_RlhTi5?dY$ BrainstormResponse: """ Generate 20 diverse race strategies. @@ -33,6 +34,7 @@ class StrategyGenerator: Args: enriched_telemetry: Recent enriched telemetry data race_context: Current race context + strategy_history: List of previous strategies for continuity Returns: BrainstormResponse with 20 strategies @@ -41,13 +43,15 @@ class StrategyGenerator: Exception: If generation fails """ logger.info(f"Generating strategies using {len(enriched_telemetry)} laps of telemetry") + if strategy_history: + logger.info(f"Including {len(strategy_history)} previous strategies in context") # Build prompt (use fast mode if enabled) if self.settings.fast_mode: from prompts.brainstorm_prompt import build_brainstorm_prompt_fast - prompt = build_brainstorm_prompt_fast(enriched_telemetry, race_context) + prompt = build_brainstorm_prompt_fast(enriched_telemetry, race_context, strategy_history or []) else: - prompt = build_brainstorm_prompt(enriched_telemetry, race_context) + prompt = build_brainstorm_prompt(enriched_telemetry, race_context, strategy_history or []) # Generate with Gemini (high temperature for creativity) response_data = await self.gemini_client.generate_json( diff --git a/ai_intelligence_layer/static/dashboard.html b/ai_intelligence_layer/static/dashboard.html index cb6a5d5..498aeb2 100644 --- a/ai_intelligence_layer/static/dashboard.html +++ b/ai_intelligence_layer/static/dashboard.html @@ -715,14 +715,14 @@ } function handleMessage(data) { - const { type, vehicle_id, lap_data, control_output, strategy, timestamp } = data; + const { type, vehicle_id, lap_data, race_context, control_output, strategy, timestamp } = data; if (type === 'vehicle_connected') { addVehicle(vehicle_id, timestamp); } else if (type === 'vehicle_disconnected') { removeVehicle(vehicle_id); } else if (type === 'lap_data') { - addLapData(vehicle_id, lap_data, control_output, strategy, timestamp); + addLapData(vehicle_id, lap_data, race_context, control_output, strategy, timestamp); } } @@ -750,7 +750,7 @@ } } - function addLapData(vehicleId, lapData, controlOutput, strategy, timestamp) { + function addLapData(vehicleId, lapData, raceContext, controlOutput, strategy, timestamp) { if (!vehicles.has(vehicleId)) { addVehicle(vehicleId, timestamp); } @@ -758,6 +758,7 @@ const vehicle = vehicles.get(vehicleId); vehicle.laps.push({ ...lapData, + race_context: raceContext, // Add race context with position and gaps control_output: controlOutput, strategy: strategy, timestamp: timestamp @@ -907,6 +908,37 @@ let bodyHtml = ''; + // Race Position section (lap_time, position, gaps) + if (lap.race_context || lap.lap_time) { + bodyHtml += ` +

+ `; + } + // Telemetry data section bodyHtml += `