|
|
|
|
|
from typing import List, Tuple |
|
|
|
|
|
import gradio as gr |
|
|
|
|
|
import qa_store |
|
|
from qa_store import normalize_question |
|
|
from loader import ( |
|
|
generate_new_manual_id, |
|
|
save_manual_qa_file, |
|
|
rebuild_combined_qa, |
|
|
manual_qa_table_data, |
|
|
sync_upload_manual_qa, |
|
|
) |
|
|
|
|
|
|
|
|
def _table() -> List[List[str]]: |
|
|
return manual_qa_table_data() |
|
|
|
|
|
|
|
|
def teacher_save_add_overwrite( |
|
|
question: str, answer: str, current_id: str |
|
|
) -> Tuple[str, str, str, List[List[str]], str]: |
|
|
""" |
|
|
Add a new manual Q&A or overwrite existing one |
|
|
with the same normalized question. |
|
|
""" |
|
|
question = (question or "").strip() |
|
|
answer = (answer or "").strip() |
|
|
current_id = current_id or "" |
|
|
|
|
|
if not question or not answer: |
|
|
msg = "❌ ກະລຸນາໃສ່ທັງຄໍາຖາມແລະຄໍາຕອບ." |
|
|
return question, answer, current_id, _table(), msg |
|
|
|
|
|
norm_q = normalize_question(question) |
|
|
entry = qa_store.MANUAL_QA_INDEX.get(norm_q) |
|
|
|
|
|
if entry: |
|
|
|
|
|
entry["q"] = question |
|
|
entry["a"] = answer |
|
|
entry["norm_q"] = norm_q |
|
|
current_id = entry["id"] |
|
|
msg = "✅ ອັບເດດ Q&A ທີ່ມີຢູ່ແລ້ວ." |
|
|
else: |
|
|
|
|
|
new_id = generate_new_manual_id() |
|
|
entry = { |
|
|
"id": new_id, |
|
|
"q": question, |
|
|
"a": answer, |
|
|
"norm_q": norm_q, |
|
|
} |
|
|
qa_store.MANUAL_QA_LIST.append(entry) |
|
|
qa_store.MANUAL_QA_INDEX[norm_q] = entry |
|
|
current_id = new_id |
|
|
msg = "✅ ບັນທຶກ Q&A ໃໝ່ສໍາເລັດ." |
|
|
|
|
|
save_manual_qa_file() |
|
|
rebuild_combined_qa() |
|
|
sync_upload_manual_qa() |
|
|
|
|
|
return question, answer, current_id, _table(), msg |
|
|
|
|
|
|
|
|
def teacher_update_current( |
|
|
question: str, answer: str, current_id: str |
|
|
) -> Tuple[str, str, str, List[List[str]], str]: |
|
|
""" |
|
|
Update the currently selected manual Q&A by id. |
|
|
""" |
|
|
question = (question or "").strip() |
|
|
answer = (answer or "").strip() |
|
|
current_id = current_id or "" |
|
|
|
|
|
if not current_id: |
|
|
msg = "❌ ກະລຸນາເລືອກ Q&A ຈາກຕາຕະລາງກ່ອນ." |
|
|
return question, answer, current_id, _table(), msg |
|
|
|
|
|
if not question or not answer: |
|
|
msg = "❌ ກະລຸນາໃສ່ທັງຄໍາຖາມແລະຄໍາຕອບ." |
|
|
return question, answer, current_id, _table(), msg |
|
|
|
|
|
entry = next((e for e in qa_store.MANUAL_QA_LIST if e["id"] == current_id), None) |
|
|
if not entry: |
|
|
msg = "⚠️ ບໍ່ພົບ Q&A ທີ່ເລືອກ." |
|
|
current_id = "" |
|
|
return question, answer, current_id, _table(), msg |
|
|
|
|
|
|
|
|
qa_store.MANUAL_QA_INDEX.pop(entry["norm_q"], None) |
|
|
|
|
|
new_norm = normalize_question(question) |
|
|
entry["q"] = question |
|
|
entry["a"] = answer |
|
|
entry["norm_q"] = new_norm |
|
|
qa_store.MANUAL_QA_INDEX[new_norm] = entry |
|
|
|
|
|
save_manual_qa_file() |
|
|
rebuild_combined_qa() |
|
|
sync_upload_manual_qa() |
|
|
|
|
|
msg = "✅ ແກ້ໄຂ Q&A ສໍາເລັດ." |
|
|
return question, answer, current_id, _table(), msg |
|
|
|
|
|
|
|
|
def teacher_delete_current( |
|
|
current_id: str, |
|
|
) -> Tuple[str, str, str, List[List[str]], str]: |
|
|
""" |
|
|
Delete the currently selected manual Q&A. |
|
|
""" |
|
|
current_id = current_id or "" |
|
|
|
|
|
if not current_id: |
|
|
msg = "❌ ກະລຸນາເລືອກ Q&A ກ່ອນຈະລຶບ." |
|
|
return "", "", current_id, _table(), msg |
|
|
|
|
|
entry = next((e for e in qa_store.MANUAL_QA_LIST if e["id"] == current_id), None) |
|
|
if not entry: |
|
|
msg = "⚠️ ບໍ່ພົບ Q&A ທີ່ຈະລຶບ." |
|
|
return "", "", "", _table(), msg |
|
|
|
|
|
qa_store.MANUAL_QA_LIST = [e for e in qa_store.MANUAL_QA_LIST if e["id"] != current_id] |
|
|
qa_store.MANUAL_QA_INDEX.pop(entry["norm_q"], None) |
|
|
|
|
|
save_manual_qa_file() |
|
|
rebuild_combined_qa() |
|
|
sync_upload_manual_qa() |
|
|
|
|
|
msg = "🗑️ ລຶບ Q&A ສໍາເລັດ." |
|
|
return "", "", "", _table(), msg |
|
|
|
|
|
|
|
|
def teacher_on_table_select( |
|
|
evt: gr.SelectData, |
|
|
) -> Tuple[str, str, str, str]: |
|
|
""" |
|
|
When teacher clicks a row in the Q&A table, load Q/A into textboxes. |
|
|
""" |
|
|
try: |
|
|
if evt is None or evt.index is None or evt.row_value is None: |
|
|
raise ValueError("Empty select event") |
|
|
|
|
|
row = list(evt.row_value) |
|
|
|
|
|
current_id = str(row[0]) if len(row) > 0 else "" |
|
|
question = str(row[1]) if len(row) > 1 else "" |
|
|
answer = str(row[2]) if len(row) > 2 else "" |
|
|
|
|
|
if not current_id: |
|
|
raise ValueError("Empty ID from selected row") |
|
|
|
|
|
msg = f"✏️ ເລືອກ Q&A ID {current_id} ສໍາລັບແກ້ໄຂ." |
|
|
except Exception as e: |
|
|
print(f"[WARN] teacher_on_table_select error: {e}") |
|
|
current_id = "" |
|
|
question = "" |
|
|
answer = "" |
|
|
msg = "⚠️ ບໍ່ສາມາດເລືອກແຖວໄດ້." |
|
|
|
|
|
return question, answer, current_id, msg |