update: change prompt instruction on endpoint generate question and feedback
This commit is contained in:
parent
26d42db33e
commit
425e9ecd3d
|
|
@ -30,17 +30,15 @@ class FileMaterialRequest(BaseModel):
|
||||||
file_name: str
|
file_name: str
|
||||||
question_type: str
|
question_type: str
|
||||||
question_count: int
|
question_count: int
|
||||||
start_page: int = 10
|
start_page: int = 24
|
||||||
|
|
||||||
class FeedbackRequest(BaseModel):
|
class FeedbackRequest(BaseModel):
|
||||||
user_answer: str
|
user_answer: str
|
||||||
expected_answer: str
|
expected_answer: str
|
||||||
|
question_text: str
|
||||||
|
|
||||||
feedback_cache = {}
|
feedback_cache = {}
|
||||||
|
|
||||||
def potong_konten(text: str, max_chars: int = 5000):
|
|
||||||
return text[:max_chars] if len(text) > max_chars else text
|
|
||||||
|
|
||||||
@app.post("/generate-from-file/")
|
@app.post("/generate-from-file/")
|
||||||
async def generate_from_file(request: FileMaterialRequest):
|
async def generate_from_file(request: FileMaterialRequest):
|
||||||
try:
|
try:
|
||||||
|
|
@ -62,55 +60,135 @@ async def generate_from_file(request: FileMaterialRequest):
|
||||||
if not text.strip():
|
if not text.strip():
|
||||||
raise HTTPException(status_code=400, detail="Isi file kosong atau tidak terbaca.")
|
raise HTTPException(status_code=400, detail="Isi file kosong atau tidak terbaca.")
|
||||||
|
|
||||||
content_bersih = potong_konten(text.strip())
|
# ==== PROMPT INSTRUKSI BERDASARKAN JENIS SOAL ====
|
||||||
|
if request.question_type == "multiple_choice":
|
||||||
|
soal_instruksi = f"""
|
||||||
|
1. Ambil satu paragraf panjang dari teks.
|
||||||
|
2. Buat **{mc_count} soal pilihan ganda** dari paragraf tersebut.
|
||||||
|
3. Soal harus berdasarkan informasi yang tertulis langsung dalam paragraf (eksplisit).
|
||||||
|
4. Hindari soal yang:
|
||||||
|
- Mengandung simpulan di luar isi
|
||||||
|
- Menambahkan tokoh, nama, atau kejadian di luar paragraf
|
||||||
|
- Jawabannya tidak bisa ditemukan dari paragraf
|
||||||
|
5. Topik soal mencakup:
|
||||||
|
- Ide pokok paragraf
|
||||||
|
- Kalimat utama
|
||||||
|
- Sinonim atau antonim (jika ada kata yang mendukung)
|
||||||
|
- Informasi eksplisit dari kalimat dalam paragraf
|
||||||
|
6. Gunakan bahasa sederhana, sesuai siswa SD kelas 3–4.
|
||||||
|
7. Bobot setiap soal **1–2**, berdasarkan tingkat kesulitan.
|
||||||
|
8. Gunakan format berikut:
|
||||||
|
|
||||||
prompt = f"""
|
**Paragraf:**
|
||||||
Buat soal latihan berdasarkan teks materi berikut untuk siswa SD kelas 3.
|
"[Isi paragraf]"
|
||||||
|
|
||||||
**Instruksi:**
|
|
||||||
1. Buat total {request.question_count} soal dengan rincian:
|
|
||||||
- Soal pilihan ganda: {mc_count}
|
|
||||||
- Soal isian: {essay_count}
|
|
||||||
|
|
||||||
2. **Untuk soal isian:**
|
|
||||||
- Ambil kutipan **minimal dua kalimat yang saling terhubung** dari teks sebagai dasar soal
|
|
||||||
- Awali dengan: **Bacalah kutipan berikut: "[kutipan]"**
|
|
||||||
- Buat pertanyaan berdasarkan kutipan tersebut
|
|
||||||
- Sertakan **jawaban singkat**
|
|
||||||
- Beri bobot antara **3–5** sesuai kompleksitas
|
|
||||||
|
|
||||||
3. **Untuk soal pilihan ganda (jika ada):**
|
|
||||||
- Ambil kutipan **1 kalimat yang relevan** dari teks
|
|
||||||
- Buat pertanyaan dan 4 pilihan jawaban (A–D)
|
|
||||||
- Beri jawaban benar dan bobot antara **1–2** sesuai tingkat kesulitan
|
|
||||||
|
|
||||||
4. Gunakan bahasa sederhana dan sesuai dengan siswa SD kelas 3.
|
|
||||||
|
|
||||||
5. Jangan menambahkan informasi di luar teks materi.
|
|
||||||
|
|
||||||
**Format Output:**
|
|
||||||
""" + ("""
|
|
||||||
**Soal Pilihan Ganda:**
|
**Soal Pilihan Ganda:**
|
||||||
1. Bacalah kutipan berikut: "[2 kalimat atau lebih dari teks]"
|
1. [Pertanyaan]
|
||||||
Pertanyaan: [Pertanyaan]
|
A. ...
|
||||||
A. [Opsi A]
|
B. ...
|
||||||
B. [Opsi B]
|
C. ...
|
||||||
C. [Opsi C]
|
D. ...
|
||||||
D. [Opsi D]
|
Jawaban: ...
|
||||||
Jawaban: [Huruf Opsi]
|
Bobot: ...
|
||||||
Bobot: [1 atau 2]
|
|
||||||
""" if mc_count > 0 else "") + ("""
|
|
||||||
|
|
||||||
**Soal Isian:**
|
|
||||||
1. Bacalah kutipan berikut: "[2 kalimat atau lebih dari teks]". [Pertanyaan]
|
|
||||||
Jawaban: [Jawaban]
|
|
||||||
Bobot: [3 - 5]
|
|
||||||
""" if essay_count > 0 else "") + f"""
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Materi:**
|
✅ Contoh soal:
|
||||||
{content_bersih}
|
|
||||||
|
**Paragraf:**
|
||||||
|
"Pak Budi memelihara ayam, bebek, dan kambing. Setiap pagi, ia memberi makan ternaknya dengan penuh kasih sayang."
|
||||||
|
|
||||||
|
**Contoh Soal Pilihan Ganda:**
|
||||||
|
1. Apa hewan yang dipelihara Pak Budi?
|
||||||
|
A. Kucing
|
||||||
|
B. Ayam dan kambing
|
||||||
|
C. Anjing dan bebek
|
||||||
|
D. Ikan dan sapi
|
||||||
|
Jawaban: B
|
||||||
|
Bobot: 1
|
||||||
|
|
||||||
|
2. Apa sinonim dari kata 'ternak' dalam paragraf tersebut?
|
||||||
|
A. Hewan peliharaan
|
||||||
|
B. Sayuran
|
||||||
|
C. Alat tani
|
||||||
|
D. Makanan ternak
|
||||||
|
Jawaban: A
|
||||||
|
Bobot: 2
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
elif request.question_type == "essay":
|
||||||
|
soal_instruksi = f"""
|
||||||
|
1. Ambil satu paragraf panjang dari teks.
|
||||||
|
2. Buat **{essay_count} soal isian** dari paragraf tersebut.
|
||||||
|
3. Soal harus berasal dari informasi eksplisit yang tertulis dalam paragraf.
|
||||||
|
4. Hindari soal yang:
|
||||||
|
- Mengandung penalaran atau simpulan dari luar isi
|
||||||
|
- Mengandung tokoh, tempat, atau kejadian tambahan
|
||||||
|
5. Topik soal mencakup:
|
||||||
|
- Ide pokok paragraf
|
||||||
|
- Kalimat penting
|
||||||
|
- Karakter tokoh
|
||||||
|
- Sinonim atau antonim (jika tersedia dalam paragraf)
|
||||||
|
6. Gunakan bahasa sederhana, sesuai siswa SD kelas 3–4.
|
||||||
|
7. **Ingat: Bobot soal isian HARUS antara 3 hingga 5. Tidak boleh menggunakan bobot 1 atau 2.**
|
||||||
|
8. Gunakan format berikut:
|
||||||
|
|
||||||
|
**Paragraf:**
|
||||||
|
"[Isi paragraf]"
|
||||||
|
|
||||||
|
**Soal Isian:**
|
||||||
|
1. [Pertanyaan]
|
||||||
|
Jawaban: ...
|
||||||
|
Bobot: [3, 4, atau 5 saja — bukan angka lain]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
✅ Contoh soal (ikuti strukturnya):
|
||||||
|
|
||||||
|
**Paragraf:**
|
||||||
|
"Pak Ali menanam padi di sawah setiap musim tanam. Ia bekerja keras agar panennya berhasil."
|
||||||
|
|
||||||
|
**Contoh Soal Isian:**
|
||||||
|
1. Apa yang ditanam Pak Ali di sawah?
|
||||||
|
Jawaban: Padi
|
||||||
|
Bobot: 3
|
||||||
|
|
||||||
|
2. Mengapa Pak Ali bekerja keras?
|
||||||
|
Jawaban: Agar panennya berhasil
|
||||||
|
Bobot: 4
|
||||||
|
|
||||||
|
3. Apa sinonim dari kata 'bekerja keras' dalam paragraf tersebut?
|
||||||
|
Jawaban: Rajin atau tekun
|
||||||
|
Bobot: 5
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
# ==== FINAL PROMPT ====
|
||||||
|
prompt = f"""
|
||||||
|
Kamu adalah asisten guru SD kelas 3 dan 4.
|
||||||
|
|
||||||
|
Tugasmu adalah membuat soal literasi dari teks di bawah ini. Soal HARUS berdasarkan isi teks, tanpa menambahkan informasi dari luar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🎯 Tujuan:
|
||||||
|
Buat **{request.question_count} soal literasi** berdasarkan **satu paragraf** untuk masing-masing jenis soal.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📌 Instruksi Umum:
|
||||||
|
- Gunakan paragraf berbeda untuk soal pilihan ganda dan isian (jika kedua jenis digunakan).
|
||||||
|
- Jangan menambahkan nama tokoh, tempat, atau kejadian di luar isi paragraf.
|
||||||
|
- Bahasa harus sederhana dan mudah dipahami siswa SD.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📌 Instruksi Soal:
|
||||||
|
{soal_instruksi}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📚 Teks:
|
||||||
|
{text.strip()}
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
logging.info("Mengirim prompt ke Ollama...")
|
logging.info("Mengirim prompt ke Ollama...")
|
||||||
|
|
@ -146,15 +224,17 @@ async def generate_feedback(request: FeedbackRequest):
|
||||||
try:
|
try:
|
||||||
user_answer = request.user_answer.strip()
|
user_answer = request.user_answer.strip()
|
||||||
expected_answer = request.expected_answer.strip()
|
expected_answer = request.expected_answer.strip()
|
||||||
|
question_text = request.question_text.strip()
|
||||||
|
|
||||||
prompt_hash = hashlib.sha256(f"{user_answer}|{expected_answer}".encode()).hexdigest()
|
prompt_hash = hashlib.sha256(f"{user_answer}|{expected_answer}|{question_text}".encode()).hexdigest()
|
||||||
if prompt_hash in feedback_cache:
|
if prompt_hash in feedback_cache:
|
||||||
logging.info("Feedback dari cache.")
|
logging.info("Feedback dari cache.")
|
||||||
return {"feedback": feedback_cache[prompt_hash]}
|
return {"feedback": feedback_cache[prompt_hash]}
|
||||||
|
|
||||||
prompt = f"""
|
prompt = f"""
|
||||||
Kamu adalah asisten pengajar untuk siswa SD kelas 3. Siswa memberikan jawaban berikut untuk soal isian.
|
Kamu adalah asisten pengajar untuk siswa SD kelas 3. Berikut ini adalah soal isian, jawaban siswa, dan jawaban ideal.
|
||||||
|
|
||||||
|
**Soal:** {question_text}
|
||||||
**Jawaban Siswa:** {user_answer}
|
**Jawaban Siswa:** {user_answer}
|
||||||
**Jawaban Ideal:** {expected_answer}
|
**Jawaban Ideal:** {expected_answer}
|
||||||
|
|
||||||
|
|
@ -162,7 +242,7 @@ Beri feedback singkat dan membangun, maksimal 2 kalimat. Gunakan bahasa yang mud
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logging.info("Mengirim prompt feedback ke Ollama...")
|
logging.info("Mengirim prompt feedback ke Ollama...")
|
||||||
async with httpx.AsyncClient(timeout=60) as client:
|
async with httpx.AsyncClient(timeout=300) as client:
|
||||||
response = await client.post(OLLAMA_URL, json={
|
response = await client.post(OLLAMA_URL, json={
|
||||||
"model": "llama3.1:latest",
|
"model": "llama3.1:latest",
|
||||||
"prompt": prompt,
|
"prompt": prompt,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import os
|
||||||
from docx import Document
|
from docx import Document
|
||||||
import fitz
|
import fitz
|
||||||
|
|
||||||
def read_text_from_file(filepath: str, start_page: int = 0, max_chars: int = 3000) -> str:
|
def read_text_from_file(filepath: str, start_page: int = 0, max_chars: int = 5000) -> str:
|
||||||
ext = os.path.splitext(filepath)[1].lower()
|
ext = os.path.splitext(filepath)[1].lower()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user