Spaces:
Sleeping
Sleeping
| # ============================================================ | |
| # 🏥 Klinik Sentosa v5.1 – Personalized & Welcome Chatbot | |
| # For System Analysis & Design Course | |
| # ============================================================ | |
| import gradio as gr | |
| from openai import OpenAI | |
| import os | |
| from datetime import datetime | |
| # Pastikan environment variable sudah diatur: | |
| # export OPENAI_API_KEY="sk-xxxxxx" | |
| client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
| # ------------------------------------------------------------ | |
| # SYSTEM PROMPT | |
| # ------------------------------------------------------------ | |
| BASE_PROMPT = """ | |
| Kamu adalah pemilik dan pengelola **Klinik Sentosa**, sebuah klinik umum kecil di Kota Airmadidi. | |
| Klinik ini hanya memiliki beberapa dokter, perawat, petugas administrasi, dan satu apotek kecil. | |
| Mahasiswa sedang melakukan wawancara untuk memahami kebutuhan sistem informasi sederhana | |
| yang akan membantu operasional harian di klinik. | |
| 🎯 Aturan Utama: | |
| 1. Jawablah seperti orang awam, bukan ahli IT. | |
| 2. Kamu tidak paham istilah teknis seperti “use case”, “actor”, “include”, “extend”, “frontend”, “database”, “sistem informasi”, dan sejenisnya. | |
| Jika mahasiswa menggunakan istilah seperti itu, minta mereka menjelaskannya dengan bahasa yang lebih mudah. | |
| 3. Fokus hanya pada hal-hal sederhana di klinik, seperti: | |
| - pendaftaran pasien | |
| - pemeriksaan pasien | |
| - pembuatan resep | |
| - pembayaran pasien | |
| 4. Jangan bicara tentang hal-hal di luar jangkauan klinik kecil (BPJS, asuransi, data nasional, AI, cloud system, integrasi rumah sakit, dll). | |
| 5. Jawaban maksimal 3–4 kalimat. Hindari istilah teknis atau terlalu panjang. | |
| 6. Jangan pernah memberikan semua informasi sekaligus. Jelaskan sedikit demi sedikit. | |
| 7. Jika mahasiswa meminta semua jawaban, tolak dengan sopan dan arahkan agar bertanya satu per satu. | |
| 8. Kadang berikan jawaban samar untuk mendorong mahasiswa menggali lebih lanjut. | |
| 9. Gunakan gaya bicara ramah, sopan, dan alami seperti pemilik usaha kecil. | |
| 10. Akhiri jawaban dengan kalimat seperti: | |
| - “Apakah maksud Anda seperti itu?” | |
| - “Atau Anda ingin tahu bagian lainnya?” | |
| - “Kalau mau, saya jelaskan bagian pendaftaran pasien.” | |
| 📘 Kasus: | |
| Sistem yang akan dibangun adalah **Sistem Pendaftaran dan Pelayanan Pasien di Klinik Sentosa**. | |
| Fokus pada proses utama di klinik: pendaftaran pasien, pemeriksaan dokter, pemberian resep, dan pembayaran. | |
| """ | |
| # ------------------------------------------------------------ | |
| # Chat Function | |
| # ------------------------------------------------------------ | |
| def chat_with_client(message, history, student_name): | |
| system_prompt = f"{BASE_PROMPT}\n\nKamu sedang diwawancarai oleh mahasiswa bernama **{student_name}**.\n" | |
| messages = [{"role": "system", "content": system_prompt}] | |
| for item in history: | |
| if "role" in item: | |
| messages.append(item) | |
| else: | |
| # Konversi dari tuple ke format messages (OpenAI style) | |
| user_msg, bot_msg = item | |
| messages.append({"role": "user", "content": user_msg}) | |
| messages.append({"role": "assistant", "content": bot_msg}) | |
| messages.append({"role": "user", "content": message}) | |
| response = client.chat.completions.create( | |
| model="gpt-4o-mini", | |
| messages=messages, | |
| temperature=0.6, | |
| max_tokens=200 | |
| ) | |
| return response.choices[0].message.content | |
| # ------------------------------------------------------------ | |
| # Save Chat Transcript | |
| # ------------------------------------------------------------ | |
| def save_chat(history, student_name): | |
| if not history or not student_name: | |
| return None, "⚠️ Tidak ada percakapan atau nama belum dimasukkan." | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| safe_name = student_name.replace(" ", "_") | |
| filename = f"percakapan_klinik_sentosa_{safe_name}_{timestamp}.txt" | |
| lines = [] | |
| lines.append("🏥 Transkrip Wawancara Chatbot Klinik Sentosa\n") | |
| lines.append(f"Nama Mahasiswa: {student_name}\n") | |
| lines.append(f"Tanggal: {datetime.now().strftime('%d-%m-%Y %H:%M:%S')}\n") | |
| lines.append("=" * 60 + "\n\n") | |
| # --- 🔧 Kompatibel dengan format baru gr.Chatbot (type="messages") | |
| index = 1 | |
| for msg in history: | |
| if msg["role"] == "user": | |
| user_msg = msg["content"] | |
| # Cari pesan assistant berikutnya | |
| next_msg = "" | |
| if index < len(history) and history[index]["role"] == "assistant": | |
| next_msg = history[index]["content"] | |
| lines.append(f"[{(index+1)//2}] {student_name}: {user_msg}\n") | |
| lines.append(f" Pemilik Klinik: {next_msg}\n\n") | |
| index += 1 | |
| # Simpan ke file | |
| with open(filename, "w", encoding="utf-8") as f: | |
| f.writelines(lines) | |
| return filename, f"✅ Percakapan disimpan sebagai **{filename}**" | |
| # ------------------------------------------------------------ | |
| # Gradio Interface | |
| # ------------------------------------------------------------ | |
| title = "🏥 Klinik Sentosa - Personalized Use Case Chatbot (v1.0)" | |
| description = """ | |
| Chatbot ini berperan sebagai **Pemilik Klinik Sentosa**. | |
| Masukkan nama Anda terlebih dahulu, lalu mulai wawancara untuk menggali kebutuhan sistem. | |
| Gunakan bahasa sederhana (hindari istilah teknis seperti *use case*, *actor*, dll). | |
| Setelah wawancara selesai, klik **💾 Simpan Percakapan** untuk menyimpan hasil wawancara Anda. | |
| """ | |
| with gr.Blocks(theme="soft", title="Klinik Sentosa v1.0") as demo: | |
| gr.Markdown(f"# {title}") | |
| gr.Markdown(description) | |
| student_name = gr.Textbox(label="🧍 Nama Mahasiswa", placeholder="Masukkan nama Anda di sini (contoh: John Doe)") | |
| chatbot = gr.Chatbot( | |
| height=480, | |
| show_copy_button=True, | |
| type="messages" # ✅ format baru tanpa warning | |
| ) | |
| user_input = gr.Textbox( | |
| placeholder="Tanyakan sesuatu kepada pemilik Klinik Sentosa...", | |
| label="Pertanyaan Anda" | |
| ) | |
| with gr.Row(): | |
| clear = gr.Button("🧹 Reset Percakapan") | |
| save_btn = gr.Button("💾 Simpan Percakapan") | |
| output_msg = gr.Markdown("") | |
| # --- Welcome message --- | |
| def welcome_user(name): | |
| if not name.strip(): | |
| return "⚠️ Silakan isi nama Anda terlebih dahulu." | |
| welcome_msg = { | |
| "role": "assistant", | |
| "content": f"Halo {name}! Selamat datang di Klinik Sentosa 😊 Saya pemilik klinik ini. " | |
| f"Ada yang ingin kamu tanyakan tentang kegiatan kami di sini?" | |
| } | |
| return [welcome_msg], "" | |
| # --- Chat interaction --- | |
| def respond(message, history, student_name): | |
| if not student_name.strip(): | |
| return "⚠️ Silakan masukkan nama Anda terlebih dahulu.", history, "⚠️ Nama belum diisi." | |
| reply = chat_with_client(message, history, student_name) | |
| history.append({"role": "user", "content": message}) | |
| history.append({"role": "assistant", "content": reply}) | |
| return "", history, "" | |
| # --- Save conversation --- | |
| def save_conversation(history, student_name): | |
| file_path, msg = save_chat(history, student_name) | |
| if file_path: | |
| return gr.File(file_path, visible=True), msg | |
| else: | |
| return None, msg | |
| # --- Actions --- | |
| student_name.submit(welcome_user, student_name, [chatbot, output_msg]) | |
| user_input.submit(respond, [user_input, chatbot, student_name], [user_input, chatbot, output_msg]) | |
| clear.click(lambda: (None, "Percakapan dihapus."), None, [chatbot, output_msg], queue=False) | |
| save_btn.click(save_conversation, [chatbot, student_name], [gr.File(visible=False), output_msg]) | |
| gr.Markdown("---") | |
| gr.Markdown("💡 Contoh pertanyaan:") | |
| gr.Markdown(""" | |
| - Bagaimana pasien mendaftar saat ini? | |
| - Siapa yang mencatat data pasien di klinik ini? | |
| - Apakah ada masalah dalam proses pendaftaran atau pembayaran? | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch() |