Team Ai
Apppublic

theavinash02/llm-code-deployer

sourceHugging Facemitupdated 1y agoView on Hugging Face
1likes
app.py101 linesDownload Raw Back to root
1import os
2import requests
3import time
4from fastapi import FastAPI, BackgroundTasks, HTTPException, Request
5from pydantic import BaseModel, HttpUrl
6from typing import List, Optional
7from dotenv import load_dotenv
8
9from utils import decode_attachment
10from llm_handler import generate_app_code, generate_readme
11from github_handler import deploy_project, create_or_get_repo, get_file_content
12
13load_dotenv()
14app = FastAPI()
15STUDENT_SECRET = os.getenv("STUDENT_SECRET")
16
17# --- Pydantic Models for automatic request validation ---
18class Attachment(BaseModel):
19    name: str
20    url: str
21
22class TaskRequest(BaseModel):
23    email: str
24    secret: str
25    task: str
26    round: int
27    nonce: str
28    brief: str
29    checks: List[str]
30    evaluation_url: HttpUrl
31    attachments: Optional[List[Attachment]] = None
32
33# --- Background Task Processing Logic ---
34def process_task(data: TaskRequest):
35    """The main function to handle the build and deploy process."""
36    print(f"Processing task: {data.task} (Round {data.round})")
37    brief = data.brief
38    
39    if data.attachments:
40        for att in data.attachments:
41            decoded = decode_attachment(att.dict())
42            if decoded:
43                brief += f"\n\n--- Attachment: {decoded['name']} ---\n{decoded['content']}"
44
45    code_to_update = None
46    if data.round > 1:
47        repo = create_or_get_repo(data.task)
48        code_to_update = get_file_content(repo, 'index.html')
49        if not code_to_update:
50            print("Warning: Could not fetch existing code for round 2.")
51
52    app_code = generate_app_code(brief, existing_code=code_to_update)
53    if not app_code:
54        print("Error: LLM failed to generate code."); return
55
56    readme_content = generate_readme(brief, app_code)
57    
58    files_to_commit = {'index.html': app_code, 'README.md': readme_content}
59    repo_details = deploy_project(data.task, files_to_commit, data.round)
60
61    payload = {
62        "email": data.email, "task": data.task, "round": data.round,
63        "nonce": data.nonce, "repo_url": repo_details['repo_url'],
64        "commit_sha": repo_details['commit_sha'], "pages_url": repo_details['pages_url'],
65    }
66    
67    notify_evaluation(str(data.evaluation_url), payload)
68
69def notify_evaluation(url: str, payload: dict):
70    """Sends a POST request to the evaluation URL with exponential backoff retries."""
71    max_retries, delay = 5, 1
72    for i in range(max_retries):
73        try:
74            print(f"Notifying evaluation server at {url}...")
75            response = requests.post(url, json=payload, headers={'Content-Type': 'application/json'})
76            if response.status_code == 200:
77                print("Notification successful!"); return
78            else:
79                print(f"Attempt {i+1} failed with status {response.status_code}: {response.text}")
80        except requests.exceptions.RequestException as e:
81            print(f"Attempt {i+1} failed with exception: {e}")
82        
83        if i < max_retries - 1:
84            print(f"Retrying in {delay} seconds..."); time.sleep(delay); delay *= 2
85    
86    print("Failed to notify evaluation server after all retries.")
87
88# --- API Endpoint ---
89@app.post("/api-endpoint")
90async def handle_request(task_request: TaskRequest, background_tasks: BackgroundTasks):
91    """API endpoint to receive, validate, and process task requests."""
92    if task_request.secret != STUDENT_SECRET:
93        raise HTTPException(status_code=401, detail="Unauthorized: Invalid secret")
94    
95    background_tasks.add_task(process_task, task_request)
96    
97    return {"message": "Request received and is being processed."}
98
99@app.get("/")
100def read_root():
101    return {"status": "ok", "message": "API is running. Send POST requests to /api-endpoint"}