from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import List, Dict, Optional import httpx import os import json from dotenv import load_dotenv load_dotenv() app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY") MODEL_NAME = "google/gemini-2.0-flash-exp:free" class Answers(BaseModel): initial_params: Dict[str, str] follow_up_answers: Dict[str, str] @app.get("/") async def root(): return {"message": "Callsign Generator API"} @app.post("/questions") async def get_questions(answers: Answers): prompt = f""" Based on the following user preferences for a CB radio callsign: Initial Params: {json.dumps(answers.initial_params)} Previous Answers: {json.dumps(answers.follow_up_answers)} Generate 1-3 relevant and short follow-up questions to help refine the callsign. Return ONLY a JSON object with the format: {{ "questions": [ "question 1", "question 2" ] }} Respond in Swedish. """ if not OPENROUTER_API_KEY: return {"questions": ["Config error: OPENROUTER_API_KEY missing"]} try: async with httpx.AsyncClient() as client: response = await client.post( "https://openrouter.ai/api/v1/chat/completions", headers={ "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json", }, json={ "model": MODEL_NAME, "messages": [{"role": "user", "content": prompt}], "response_format": { "type": "json_object" } }, timeout=30.0 ) result = response.json() if 'choices' not in result: return {"questions": [f"API Error: {result.get('error', 'Unknown error')}"]} content = result['choices'][0]['message']['content'] return json.loads(content) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.post("/generate") async def generate_callsign(answers: Answers): prompt = f""" Based on the following user preferences for a CB radio callsign: Initial Params: {json.dumps(answers.initial_params)} Previous Answers: {json.dumps(answers.follow_up_answers)} Generate a realistic CB callsign and a short motivation. Return ONLY a JSON object with the format: {{ "callsign": "", "reason": "" }} Respond in Swedish. """ if not OPENROUTER_API_KEY: return {"callsign": "ERROR", "reason": "OPENROUTER_API_KEY missing"} try: async with httpx.AsyncClient() as client: response = await client.post( "https://openrouter.ai/api/v1/chat/completions", headers={ "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json", }, json={ "model": MODEL_NAME, "messages": [{"role": "user", "content": prompt}], "response_format": { "type": "json_object" } }, timeout=30.0 ) result = response.json() if 'choices' not in result: return {"callsign": "ERROR", "reason": f"API Error: {result.get('error', 'Unknown error')}"} content = result['choices'][0]['message']['content'] return json.loads(content) except Exception as e: raise HTTPException(status_code=500, detail=str(e))