NiketKakkar's picture
change
ccecc26
Raw
History Blame Contribute Delete
3.49 kB
import modal
from modal_backend.commentary import app
model_volume = modal.Volume.from_name("f1-model-cache", create_if_missing=True)
image = (
modal.Image.debian_slim(python_version="3.11")
.pip_install(
"torch==2.4.0",
extra_index_url="https://download.pytorch.org/whl/cu121",
)
.pip_install(
"transformers==4.51.0",
"accelerate>=0.30.0",
"huggingface-hub>=0.22.0",
"sentencepiece",
)
.env({"HF_HOME": "/model-cache", "TRANSFORMERS_CACHE": "/model-cache"})
)
MODEL_ID = "nvidia/Llama-3.1-Nemotron-Nano-8B-v1"
SYSTEM_PROMPT = """You are a senior F1 strategist with deep knowledge of historical races.
The user will describe a real race and change one variable.
Your task:
1. Briefly acknowledge the actual race outcome (1 sentence)
2. Reason through how the changed variable affects pit windows, undercut/overcut risk, tire deg, and track position (3–5 sentences)
3. Narrate the alternate outcome with specific lap numbers and position changes
4. Produce a plausible alternate final top-5
Be specific. Reference real team strategies and driver tendencies."""
def _load_model():
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
torch_dtype=torch.bfloat16,
device_map="auto",
trust_remote_code=True,
)
model.eval()
return model, tokenizer
@app.function(
image=image,
gpu="A100",
timeout=300,
volumes={"/model-cache": model_volume},
secrets=[modal.Secret.from_name("hf-token")],
)
def reason_strategy(prompt: str, warmup: bool = False) -> dict:
import os
import torch
hf_token = os.environ.get("HF_TOKEN", "")
if hf_token:
from huggingface_hub import login
login(token=hf_token)
model, tokenizer = _load_model()
if warmup:
return {"status": "warm"}
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": prompt},
]
input_text = tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
inputs = tokenizer(input_text, return_tensors="pt").to("cuda")
with torch.no_grad():
output_ids = model.generate(
**inputs,
max_new_tokens=512,
do_sample=True,
temperature=0.7,
top_p=0.9,
pad_token_id=tokenizer.eos_token_id,
)
new_tokens = output_ids[0][inputs["input_ids"].shape[-1]:]
reasoning_chain = tokenizer.decode(new_tokens, skip_special_tokens=True).strip()
return {"reasoning_chain": reasoning_chain}
@app.local_entrypoint()
def main():
sample_prompt = (
"Race: 2023 British Grand Prix\n"
"Original outcome: Verstappen won from pole, Hamilton finished P4 after a late pit.\n"
"User change: What if Hamilton had pitted 5 laps earlier on lap 30 for fresh mediums?"
)
print("Running warmup...")
result = reason_strategy.remote(prompt="", warmup=True)
print(f"Warmup result: {result}")
print("\nRunning strategy inference...")
result = reason_strategy.remote(prompt=sample_prompt, warmup=False)
reasoning = result.get("reasoning_chain", "")
assert reasoning, "reasoning_chain is empty — inference failed"
print(f"\nReasoning chain:\n{reasoning}")