import json import os import uvicorn import urllib.request import urllib.error from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse, JSONResponse app = FastAPI() def call_gemini(prompt: str) -> str: api_key = os.environ.get("GEMINI_API_KEY", "") if not api_key: raise ValueError("GEMINI_API_KEY is not set in environment variables") url = ( "https://generativelanguage.googleapis.com/v1beta/models/" "gemini-1.5-flash:generateContent?key=" + api_key ) payload = json.dumps({ "contents": [{"parts": [{"text": prompt}]}], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 1000 } }).encode("utf-8") req = urllib.request.Request( url, data=payload, headers={"Content-Type": "application/json"}, method="POST" ) try: with urllib.request.urlopen(req, timeout=30) as resp: data = json.loads(resp.read().decode("utf-8")) except urllib.error.HTTPError as e: error_body = e.read().decode("utf-8") raise ValueError("Gemini HTTP error " + str(e.code) + ": " + error_body) return data["candidates"][0]["content"]["parts"][0]["text"] @app.post("/analyze") async def analyze(request: Request): try: body = await request.json() user_data = body["user_data"] answers = body["answers"] scores = body["scores"] answers_text = "" for a in answers: answers_text += "- [" + a["category"] + "] " + a["question"][:60] + "... Answer: " + a["answer"][:50] + "\n" prompt = ( "You are an expert psychologist and intelligence analyst.\n" "Analyze these test results and return a JSON report.\n\n" "User: " + user_data["name"] + ", Age " + str(user_data["age"]) + ", " + user_data["edu"] + ", likes " + user_data["interest"] + "\n\n" "Scores: Logical=" + str(scores["logical"]) + " Creative=" + str(scores["creative"]) + " Spatial=" + str(scores["spatial"]) + " Verbal=" + str(scores["verbal"]) + " Emotional=" + str(scores["emotional"]) + "\n\n" "Answers:\n" + answers_text + "\n" "Return ONLY valid JSON, no markdown, no backticks, no extra text:\n" '{"intel_type":"3-4 sentences about dominant intelligence","scientist_name":"matching historical scientist","scientist_title":"their field","scientist_icon":"emoji","scientist_reason":"2-3 sentences why similar","jobs":["job1","job2","job3","job4"],"jobs_reason":"2 sentences why suitable","advice":"2-3 sentences personal advice"}' ) text = call_gemini(prompt) text = text.replace("```json", "").replace("```", "").strip() # Find JSON in response start = text.find("{") end = text.rfind("}") + 1 if start == -1 or end == 0: raise ValueError("No JSON found in response: " + text[:200]) result = json.loads(text[start:end]) return JSONResponse(content=result) except Exception as e: return JSONResponse(content={"error": str(e)}, status_code=500) @app.get("/", response_class=HTMLResponse) async def root(): try: with open("index.html", "r", encoding="utf-8") as f: return f.read() except FileNotFoundError: return HTMLResponse("

index.html not found

", status_code=404) @app.get("/health") async def health(): key = os.environ.get("GEMINI_API_KEY", "") return { "status": "ok", "gemini_key_set": bool(key), "key_preview": key[:10] + "..." if key else "NOT SET" } if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=7860)