File size: 4,823 Bytes
ed9ec1a
 
 
 
 
c9eadad
4ec9d10
ed9ec1a
4ec9d10
ed9ec1a
 
 
4ec9d10
ed9ec1a
 
4ec9d10
ed9ec1a
 
 
 
 
 
 
 
4ec9d10
ed9ec1a
 
 
 
5518ae7
ed9ec1a
4ec9d10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed9ec1a
 
c8d901a
064a7fb
c393dc6
 
064a7fb
 
 
 
 
 
5dbf5ee
 
 
 
 
 
 
 
 
abee3b5
4ec9d10
abee3b5
 
 
4ec9d10
5518ae7
abee3b5
 
 
 
 
 
 
 
3eedfce
ed9ec1a
 
 
4ec9d10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed9ec1a
 
 
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
132
133
134
135
136
137
138
139
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) ===
@app.post("/generate")
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 ===
@app.post("/generate-soal")
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 ===
@app.get("/")
async def root():
    return {"message": "Gemini endpoint aktif bro! 🚀"}