Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| from fastapi.middleware.cors import CORSMiddleware | |
| import os | |
| import google.generativeai as genai | |
| from typing import List, Optional | |
| from uuid import uuid4 | |
| # Konfigurasi Gemini API | |
| genai.configure(api_key=os.environ["GEMINI_API_KEY"]) | |
| model = genai.GenerativeModel("gemini-1.5-flash") | |
| # Init FastAPI | |
| app = FastAPI() | |
| # CORS biar frontend bebas akses | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # === MODEL UNTUK REQUEST === | |
| class PromptRequest(BaseModel): | |
| prompt: str | |
| max_new_tokens: int = 300 | |
| temperature: float = 0.7 | |
| history: Optional[List[str]] = [] | |
| class GenerateSoalRequest(BaseModel): | |
| topic: str | |
| level: Optional[int] = 1 | |
| tipe_pertanyaan: Optional[str] = None # "pilihan_ganda", "isian_kosong", "benar_salah" | |
| # === HELPER FUNCTION === | |
| def format_prompt_soal(topic, tipe=None, level=1): | |
| tipe_instruksi = f"Tipe soal yang diminta adalah '{tipe}'." if tipe else "Tipe soal boleh bebas." | |
| return f""" | |
| Buatkan satu soal latihan grammar Bahasa Inggris untuk topik: "{topic}". | |
| {tipe_instruksi} | |
| Level kesulitan: {level}/5. | |
| Format keluaran harus dalam JSON seperti berikut: | |
| {{ | |
| "text_pertanyaan": "Tulis pertanyaan di sini...", | |
| "tipe_pertanyaan": "pilihan_ganda | isian_kosong | benar_salah", | |
| "opsi": {{ | |
| "a": "Pilihan A", | |
| "b": "Pilihan B", | |
| "c": "Pilihan C", | |
| "d": "Pilihan D" | |
| }}, | |
| "jawaban_benar": "b", | |
| "penjelasan": "Berikan penjelasan edukatif tentang jawaban yang benar." | |
| }} | |
| Catatan: | |
| - Jika tipe soal bukan "pilihan_ganda", sesuaikan struktur 'opsi' (bisa null atau objek true/false). | |
| - Jangan tambahkan teks selain JSON. | |
| - Jangan tambahkan penjelasan tambahan di luar JSON. | |
| Mulai sekarang, buat 1 soal untuk topik di atas dan jawab dalam format JSON! | |
| """ | |
| # === ENDPOINT UNTUK PERBAIKAN KELUARAN MODEL (EXISTING) === | |
| async def generate_text(req: PromptRequest): | |
| try: | |
| system_prompt = f""" | |
| Kamu adalah asisten edukatif untuk sistem pembelajaran Bahasa Inggris. | |
| Berikut ini adalah hasil dari model LLaMA: | |
| --- MULAI --- | |
| {req.prompt} | |
| --- SELESAI --- | |
| Tugas kamu adalah: | |
| 1. Periksa dan perbaiki kesalahan tata bahasa dan struktur kalimat jika perlu. | |
| 2. Ubah seluruh jawaban ke dalam Bahasa Indonesia dengan gaya edukatif dan mudah dipahami oleh pelajar. | |
| 3. Pertahankan contoh kalimat dalam Bahasa Inggris sebagaimana aslinya. Jangan diterjemahkan. | |
| 4. Pertahankan istilah grammar atau kata yang diapit tanda petik seperti "present continuous", "am", "is", "are", dll. | |
| 5. Jangan menambahkan penjelasan yang tidak berkaitan dengan topik grammar dalam jawaban. | |
| 6. Fokus pada konteks pembelajaran Bahasa Inggris. Jangan membahas topik lain di luar itu. | |
| 7. Jika isi jawaban terlalu panjang, buatlah ringkasan yang jelas dan tetap lengkap. | |
| Langsung tampilkan hasil akhir dalam Bahasa Indonesia tanpa menjelaskan proses atau langkah-langkah pengerjaan. | |
| """ | |
| messages = [{"role": "user", "parts": [{"text": system_prompt.strip()}]}] | |
| for msg in req.history or []: | |
| role = "user" if msg.startswith("User:") else "model" | |
| text = msg.replace("User: ", "").replace("Bot: ", "") | |
| messages.append({"role": role, "parts": [{"text": text}]}) | |
| result = model.generate_content( | |
| messages, | |
| generation_config={ | |
| "temperature": req.temperature, | |
| "max_output_tokens": req.max_new_tokens, | |
| } | |
| ) | |
| return {"generated_text": result.text} | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| # === ENDPOINT BARU UNTUK GENERATE SOAL DARI AI === | |
| async def generate_soal(req: GenerateSoalRequest): | |
| try: | |
| prompt = format_prompt_soal(req.topic, req.tipe_pertanyaan, req.level) | |
| result = model.generate_content( | |
| prompt, | |
| generation_config={"temperature": 0.8, "max_output_tokens": 512} | |
| ) | |
| # Bersihkan & parsing response (anggap Gemini kasih string JSON langsung) | |
| import json | |
| json_text = result.text.strip().split("```")[-1].strip() # Bersihin kalau ada blok kode | |
| soal_data = json.loads(json_text) | |
| soal_data["id"] = str(uuid4()) | |
| soal_data["topic_id"] = req.topic | |
| soal_data["level"] = req.level or 1 | |
| soal_data["is_ai_generated"] = True | |
| soal_data["created_at"] = str(os.getenv("TZ") or "2025-07-12T00:00:00Z") | |
| return {"soal": soal_data} | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Gagal generate soal: {e}") | |
| # === ROOT TEST === | |
| async def root(): | |
| return {"message": "Gemini endpoint aktif bro! 🚀"} | |