Spaces:
Sleeping
Sleeping
File size: 3,965 Bytes
46354f0 41f8b3d 46354f0 41f8b3d 46354f0 41f8b3d 64ca6f8 46354f0 64ca6f8 46354f0 2679305 46354f0 2679305 46354f0 2679305 46354f0 2679305 46354f0 64ca6f8 46354f0 cda5c64 46354f0 3283333 46354f0 2472fa3 357210d 46354f0 41f8b3d 46354f0 64ca6f8 46354f0 86932ae 46354f0 86932ae 46354f0 86932ae 46354f0 86932ae 46354f0 53a321f 41f8b3d 46354f0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
import os
import json
from typing import Literal, Dict, Any
import httpx
from fastapi import FastAPI, Query, HTTPException
from fastapi.responses import JSONResponse
app = FastAPI()
CEREBRAS_API_KEY = os.getenv("CEREBRAS_API_KEY")
CEREBRAS_API_URL = "https://api.cerebras.ai/v1/chat/completions"
def build_prompt(difficulty: str, language: str) -> str:
return f"""
あなたはクイズ作成者です。
難易度: {difficulty}
言語: {language}
次のフォーマットの JSON だけを返してください(前後に一切の文章を付けないこと):
**出力には{language}を使ってください。**
{{
"questions": [
{{
"question": "問題文({language})",
"choices": ["選択肢1", "選択肢2", "選択肢3", "選択肢4"],
"correctIndex": 0
}},
{{
"question": "問題文({language})",
"choices": ["選択肢1", "選択肢2", "選択肢3", "選択肢4"],
"correctIndex": 0
}},
{{
"question": "問題文({language})",
"choices": ["選択肢1", "選択肢2", "選択肢3", "選択肢4"],
"correctIndex": 0
}}
]
}}
制約:
- 質問は必ず3問
- 各問題は4択
- テーマは一般教養レベル(雑学など)で OK
- 難易度は easy, medium, hard に応じて調整
- 最終的なアウトプットは {language}に合わせて出力
"""
async def call_cerebras_quiz_api(difficulty: str, language: str) -> Dict[str, Any]:
if not CEREBRAS_API_KEY:
raise RuntimeError("CEREBRAS_API_KEY is not set")
prompt = build_prompt(difficulty, language)
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {CEREBRAS_API_KEY}",
}
payload = {
"model": "gpt-oss-120b",
"messages": [
{"role": "system", "content": "You are a helpful quiz generator."},
{"role": "user", "content": prompt},
],
"temperature": 0.8,
"max_tokens": 1024,
}
async with httpx.AsyncClient(timeout=30.0) as client:
resp = await client.post(CEREBRAS_API_URL, headers=headers, json=payload)
if resp.status_code != 200:
raise RuntimeError(f"Cerebras API error: {resp.status_code}, {resp.text}")
data = resp.json()
content = data.get("choices", [{}])[0].get("message", {}).get("content", "")
# たまにモデルが ```json ... ``` で囲んでくる可能性があるので軽く掃除
cleaned = content.strip()
if cleaned.startswith("```"):
# ```json or ``` で始まるケースに対応
cleaned = cleaned.strip("`")
# 先頭行に "json" とか残っていたら落とす
if cleaned.startswith("json"):
cleaned = cleaned[len("json") :].lstrip()
try:
quiz = json.loads(cleaned)
except json.JSONDecodeError as e:
# デバッグ用に content を見たい場合は log に出す
print("Failed to parse JSON from model:", content)
raise RuntimeError(f"JSON parse error: {e}")
return quiz
@app.get("/quiz")
async def get_quiz(
difficulty: Literal["easy", "medium", "hard"] = Query("medium"),
language: str = Query("en")
):
"""
クイズを3問返すAPI。
レスポンス形式:
{
"questions": [
{
"question": "....",
"choices": ["..", "..", "..", ".."],
"correctIndex": 1
},
...
]
}
"""
try:
quiz = await call_cerebras_quiz_api(difficulty, language)
except Exception as e:
# 拡張側が扱いやすいように 500 + メッセージだけ返す
raise HTTPException(status_code=500, detail=str(e))
# 最低限のバリデーション(壊れたJSONでないかチェック)
if not isinstance(quiz, dict) or "questions" not in quiz:
raise HTTPException(status_code=500, detail="Invalid quiz format")
return JSONResponse(content=quiz)
|