# app.py import gradio as gr from model_utils import laos_science_bot from loader import manual_qa_table_data from teacher_panel import ( teacher_save_add_overwrite, teacher_update_current, teacher_delete_current, teacher_on_table_select, ) # Build Gradio UI with gr.Blocks() as demo: gr.Markdown("## ๐Ÿ˜ Laos Natural Science Chatbot โ€“ เบชเปเบฒเบฅเบฑเบšเบ™เบฑเบเบฎเบฝเบ™ เบก.1 - เบก.4") # ---------------- Student tab ---------------- with gr.Tab("๐Ÿ‘ฉโ€๐ŸŽ“ Student Chat"): gr.Markdown("เบ–เบฒเบกเบ„เปเบฒเบ–เบฒเบกเบงเบดเบ—เบฐเบเบฒเบชเบฒเบ”เบ—เบณเบกเบฐเบŠเบฒเบ”เบžเบฒเบชเบฒเบฅเบฒเบงเป„เบ”เป‰เป€เบฅเบตเบ.") gr.ChatInterface( fn=laos_science_bot, title="", description="", examples=[ "เบงเบดเบ—เบฐเบเบฒเบชเบฒเบ”เบ—เบณเบกเบฐเบŠเบฒเบ”เปเบกเปˆเบ™เบซเบเบฑเบ‡?", ], ) # ---------------- Teacher tab ---------------- with gr.Tab("๐Ÿ‘ฉโ€๐Ÿซ Teacher Panel"): gr.Markdown( "เปœเป‰เบฒเบ™เบตเป‰เปƒเบซเป‰เบ„เบนเป€เบžเบตเปˆเบก / เปเบเป‰เป„เบ‚ Q&A เป€เบญเบ‡. " "เบ„เปเบฒเบ•เบญเบšเปƒเปเปˆเบˆเบฐเบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เบ—เบฑเบ™เบ—เบตเปƒเบ™ Student Chat." ) q_box = gr.Textbox( label="เบ„เปเบฒเบ–เบฒเบก (เบžเบฒเบชเบฒเบฅเบฒเบง)", lines=3, placeholder="เบžเบดเบกเบ„เปเบฒเบ–เบฒเบกเบงเบดเบ—เบฐเบเบฒเบชเบฒเบ”เบ—เบณเบกเบฐเบŠเบฒเบ”...", ) a_box = gr.Textbox( label="เบ„เปเบฒเบ•เบญเบš (เบžเบฒเบชเบฒเบฅเบฒเบง)", lines=4, placeholder="เบžเบดเบกเบ„เปเบฒเบ•เบญเบšเบ—เบตเปˆเบ–เบทเบเบ•เป‰เบญเบ‡ เปเบฅเบฐเป€เบ‚เบปเป‰เบฒเปƒเบˆเบ‡เปˆเบฒเบ...", ) current_id_state = gr.State("") with gr.Row(): btn_save = gr.Button("๐Ÿ’พ Save Q&A (Add / Overwrite)") btn_update = gr.Button("โœ๏ธ Update current") btn_delete = gr.Button("๐Ÿ—‘๏ธ Delete current") status_md = gr.Markdown("") qa_table = gr.Dataframe( headers=["ID", "เบ„เปเบฒเบ–เบฒเบก", "เบ„เปเบฒเบ•เบญเบš"], value=manual_qa_table_data(), interactive=True, wrap=True, row_count=(0, "dynamic"), ) # wire buttons btn_save.click( fn=teacher_save_add_overwrite, inputs=[q_box, a_box, current_id_state], outputs=[q_box, a_box, current_id_state, qa_table, status_md], ) btn_update.click( fn=teacher_update_current, inputs=[q_box, a_box, current_id_state], outputs=[q_box, a_box, current_id_state, qa_table, status_md], ) btn_delete.click( fn=teacher_delete_current, inputs=[current_id_state], outputs=[q_box, a_box, current_id_state, qa_table, status_md], ) qa_table.select( fn=teacher_on_table_select, inputs=None, # we only use the event data outputs=[q_box, a_box, current_id_state, status_md], ) # ๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡ ADD THIS NEW BLOCK HERE ๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡ # This ensures that whenever the page is refreshed, the table updates # to show the REAL current data from memory. demo.load( fn=manual_qa_table_data, inputs=None, outputs=qa_table ) # ๐Ÿ‘†๐Ÿ‘†๐Ÿ‘† END OF NEW BLOCK ๐Ÿ‘†๐Ÿ‘†๐Ÿ‘† if __name__ == "__main__": demo.launch()