Spaces:
Sleeping
Sleeping
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 | |
async def health_check(): | |
"""Offentlig health check""" | |
return { | |
"status": "healthy", | |
"service": "SoActi AI Quiz API", | |
"auth_required": True | |
} | |
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) | |