import os import gradio as gr import json import time from fastapi import FastAPI, HTTPException, Depends, Header from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from pydantic import BaseModel from typing import Optional # Hent API-nøkkel fra miljøvariabler API_KEY = os.getenv("SOACTI_API_KEY") if not API_KEY: raise ValueError("SOACTI_API_KEY miljøvariabel er ikke satt!") # FastAPI app app = FastAPI(title="SoActi AI Quiz API - Secure") security = HTTPBearer() # Hardkodede spørsmål (samme som før) QUIZ_DATABASE = { "oslo": [ { "spørsmål": "Hva heter Oslos hovedflyplass?", "alternativer": ["Fornebu", "Gardermoen", "Torp", "Rygge"], "korrekt_svar": 1, "forklaring": "Oslo lufthavn Gardermoen er Oslos hovedflyplass, åpnet i 1998." }, { "spørsmål": "Hvilken fjord ligger Oslo ved?", "alternativer": ["Trondheimsfjorden", "Oslofjorden", "Hardangerfjorden", "Sognefjorden"], "korrekt_svar": 1, "forklaring": "Oslo ligger innerst i Oslofjorden." }, { "spørsmål": "Hva heter Oslos berømte operahus?", "alternativer": ["Operaen", "Den Norske Opera", "Oslo Opera House", "Operahuset"], "korrekt_svar": 3, "forklaring": "Operahuset i Oslo åpnet i 2008." } ], "bergen": [ { "spørsmål": "Hva kalles det fargerike kaiområdet i Bergen?", "alternativer": ["Bryggen", "Fisketorget", "Torgallmenningen", "Nordnes"], "korrekt_svar": 0, "forklaring": "Bryggen er UNESCOs verdensarvsted." }, { "spørsmål": "Hvilket fjell kan man ta Fløibanen opp til?", "alternativer": ["Ulriken", "Fløyen", "Løvstakken", "Sandviksfjellet"], "korrekt_svar": 1, "forklaring": "Fløibanen går opp til Fløyen, 320 meter over havet." } ], "norsk historie": [ { "spørsmål": "Hvilket år ble Norge selvstendig fra Danmark?", "alternativer": ["1814", "1905", "1821", "1830"], "korrekt_svar": 0, "forklaring": "Norge ble selvstendig fra Danmark i 1814." } ] } # API-nøkkel validering async def verify_api_key(credentials: HTTPAuthorizationCredentials = Depends(security)): if credentials.credentials != API_KEY: raise HTTPException( status_code=401, detail="Ugyldig API-nøkkel" ) return credentials.credentials # Pydantic modeller class QuizRequest(BaseModel): tema: str språk: str = "no" antall_spørsmål: int = 5 type: str = "multiple_choice" vanskelighetsgrad: int = 3 # API endepunkter @app.get("/health") async def health_check(): """Offentlig health check""" return { "status": "healthy", "service": "SoActi AI Quiz API", "auth_required": True } @app.post("/generate-quiz") async def generate_quiz_secure( request: QuizRequest, api_key: str = Depends(verify_api_key) ): """Sikret quiz-generering - krever API-nøkkel""" try: tema_lower = request.tema.lower().strip() # Finn riktige spørsmål if tema_lower in QUIZ_DATABASE: questions = QUIZ_DATABASE[tema_lower] elif "oslo" in tema_lower: questions = QUIZ_DATABASE["oslo"] elif "bergen" in tema_lower: questions = QUIZ_DATABASE["bergen"] elif "historie" in tema_lower: questions = QUIZ_DATABASE["norsk historie"] else: questions = QUIZ_DATABASE["oslo"] # Begrens antall spørsmål selected_questions = questions[:request.antall_spørsmål] return { "success": True, "questions": selected_questions, "metadata": { "tema": request.tema, "språk": request.språk, "antall_generert": len(selected_questions), "model_used": "Fallback Database", "generation_time": 0.1, "auth_verified": True } } except Exception as e: raise HTTPException( status_code=500, detail=f"Feil ved quiz-generering: {str(e)}" ) # Gradio interface (kun for testing) def generate_quiz_ui(tema, antall, api_key_input): """Gradio wrapper med API-nøkkel input""" if not api_key_input: return "❌ API-nøkkel er påkrevd" if api_key_input != API_KEY: return "❌ Ugyldig API-nøkkel" try: tema_lower = tema.lower().strip() if tema_lower in QUIZ_DATABASE: questions = QUIZ_DATABASE[tema_lower] elif "oslo" in tema_lower: questions = QUIZ_DATABASE["oslo"] elif "bergen" in tema_lower: questions = QUIZ_DATABASE["bergen"] elif "historie" in tema_lower: questions = QUIZ_DATABASE["norsk historie"] else: questions = QUIZ_DATABASE["oslo"] selected_questions = questions[:antall] output = f"✅ **Genererte {len(selected_questions)} spørsmål om '{tema}'**\n\n" output += f"🔐 **Autentisert:** Ja\n" output += f"🤖 **Modell:** Fallback Database\n" output += f"⏱️ **Tid:** 0.1s\n\n" for i, q in enumerate(selected_questions, 1): output += f"📝 **Spørsmål {i}:** {q['spørsmål']}\n" for j, alt in enumerate(q['alternativer']): marker = "✅" if j == q['korrekt_svar'] else "❌" output += f" {chr(65+j)}) {alt} {marker}\n" output += f"💡 **Forklaring:** {q['forklaring']}\n\n" return output except Exception as e: return f"❌ **Feil:** {str(e)}" # Gradio interface with gr.Blocks(title="SoActi AI Quiz API - Secure") as demo: gr.Markdown("# 🔐 SoActi AI Quiz API - Sikker Versjon") gr.Markdown("**API krever nå autentisering med Bearer token**") with gr.Row(): with gr.Column(): tema_input = gr.Textbox( label="Tema", value="Oslo", placeholder="Oslo, Bergen, Norsk historie" ) antall_input = gr.Slider( minimum=1, maximum=5, step=1, label="Antall spørsmål", value=3 ) api_key_input = gr.Textbox( label="API-nøkkel (for testing)", type="password", placeholder="Skriv inn API-nøkkel..." ) generate_btn = gr.Button("🚀 Generer Quiz", variant="primary") with gr.Column(): output = gr.Textbox( label="Generert Quiz", lines=20, placeholder="Skriv inn API-nøkkel og klikk 'Generer Quiz'..." ) generate_btn.click( fn=generate_quiz_ui, inputs=[tema_input, antall_input, api_key_input], outputs=output ) gr.Markdown("## 🔗 API Endepunkt") gr.Markdown("`POST https://Soacti-soacti-ai-quiz-api.hf.space/generate-quiz`") gr.Markdown("**Header:** `Authorization: Bearer [din-api-nøkkel]`") # Mount Gradio til FastAPI app = gr.mount_gradio_app(app, demo, path="/") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)