refs #740: add Few-shot management tab
This commit is contained in:
@@ -57,7 +57,14 @@ from src.agent_console.presentation import (
|
||||
)
|
||||
from src.agent_console.profile import AppProfile, AppProfileError, load_app_profile
|
||||
from src.poc4.qa_history import QaJudgment, QaQuestion, evaluate_sql, load_benchmark_questions
|
||||
from src.poc4.qa_history_store import QaHistoryStore, QaHistoryStoreError
|
||||
from src.poc4.qa_history_store import (
|
||||
INSPECTION_STATUSES,
|
||||
REFERENCE_KINDS,
|
||||
REFERENCE_STATUSES,
|
||||
TARGET_TYPES,
|
||||
QaHistoryStore,
|
||||
QaHistoryStoreError,
|
||||
)
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@@ -2066,6 +2073,151 @@ def _render_qa_benchmark_panel(
|
||||
return selected
|
||||
|
||||
|
||||
def _render_few_shot_management_tab(
|
||||
questions: list[QaQuestion],
|
||||
store: QaHistoryStore | None,
|
||||
store_error: str,
|
||||
) -> None:
|
||||
st.subheader("질문별 Few-shot 관리")
|
||||
st.caption(
|
||||
"고객 질답 질문에 연결된 few-shot 예제를 검토하고 수정합니다. 저장하면 검색용 embedding도 함께 다시 생성됩니다."
|
||||
)
|
||||
if store_error or store is None:
|
||||
st.warning(
|
||||
"Few-shot 관리 DB에 연결하지 못했습니다. "
|
||||
+ (store_error or "질답 이력 DB 접속 설정을 확인해 주세요.")
|
||||
)
|
||||
return
|
||||
if not questions:
|
||||
st.info("표시할 고객 질답 질문이 없습니다.")
|
||||
return
|
||||
|
||||
by_code = {question.question_code: question for question in questions}
|
||||
selected_code = st.selectbox(
|
||||
"질문 선택",
|
||||
options=tuple(by_code),
|
||||
format_func=lambda code: _question_label(by_code[code]),
|
||||
key="poc4_few_shot_question_code",
|
||||
)
|
||||
selected_question = by_code[selected_code]
|
||||
st.markdown("**선택한 질문**")
|
||||
st.write(selected_question.question_text)
|
||||
try:
|
||||
examples = store.list_vector_examples_by_case(selected_question.question_code)
|
||||
except QaHistoryStoreError as exc:
|
||||
st.error(str(exc))
|
||||
return
|
||||
if not examples:
|
||||
st.info(
|
||||
"이 질문에는 아직 연결된 few-shot 후보가 없습니다. "
|
||||
"후보 적재 작업 후 이 화면에서 검토할 수 있습니다."
|
||||
)
|
||||
return
|
||||
|
||||
example_by_id = {str(item["example_id"]): item for item in examples}
|
||||
selected_example_id = st.selectbox(
|
||||
"Few-shot 예제",
|
||||
options=tuple(example_by_id),
|
||||
format_func=lambda example_id: (
|
||||
f"예제 #{example_id} · "
|
||||
f"{example_by_id[example_id]['reference_status']} · "
|
||||
f"{example_by_id[example_id]['inspection_status']}"
|
||||
),
|
||||
key=f"poc4_few_shot_example_{selected_question.question_code}",
|
||||
)
|
||||
example = example_by_id[selected_example_id]
|
||||
st.caption(
|
||||
"검색 대상은 APPROVED 예제뿐입니다. 게임별 물리 테이블은 여기에 넣지 않고, "
|
||||
"현재 질문의 query plan이 해석하는 논리 객체 역할만 관리합니다."
|
||||
)
|
||||
if example["verified_at"]:
|
||||
st.caption(
|
||||
f"마지막 승인: {example['verified_at']} · {example['verified_by'] or '확인자 미기록'}"
|
||||
)
|
||||
|
||||
form_key = f"poc4_few_shot_form_{example['example_id']}"
|
||||
with st.form(form_key):
|
||||
question = st.text_area(
|
||||
"Few-shot 질문",
|
||||
value=example["question"],
|
||||
height=100,
|
||||
max_chars=4_000,
|
||||
)
|
||||
answer_sql = st.text_area(
|
||||
"Few-shot SQL 템플릿",
|
||||
value=example["answer_sql"],
|
||||
height=220,
|
||||
max_chars=12_000,
|
||||
help="읽기 전용 SQL 템플릿을 사용하세요. 게임별 물리 객체는 논리 placeholder로 표현합니다.",
|
||||
)
|
||||
answer_text = st.text_area(
|
||||
"설명 / 답변 보조 문구",
|
||||
value=example["answer_text"],
|
||||
height=120,
|
||||
max_chars=8_000,
|
||||
)
|
||||
left, right = st.columns(2)
|
||||
with left:
|
||||
reference_status = st.selectbox(
|
||||
"검색 상태",
|
||||
options=REFERENCE_STATUSES,
|
||||
index=REFERENCE_STATUSES.index(example["reference_status"]),
|
||||
help="APPROVED만 실제 few-shot 검색에 사용됩니다.",
|
||||
)
|
||||
reference_kind = st.selectbox(
|
||||
"참조 종류",
|
||||
options=REFERENCE_KINDS,
|
||||
index=REFERENCE_KINDS.index(example["reference_kind"]),
|
||||
)
|
||||
with right:
|
||||
target_type = st.selectbox(
|
||||
"적용 게임 범위",
|
||||
options=TARGET_TYPES,
|
||||
index=TARGET_TYPES.index(example["target_type"]),
|
||||
)
|
||||
inspection_status = st.selectbox(
|
||||
"검토 상태",
|
||||
options=INSPECTION_STATUSES,
|
||||
index=INSPECTION_STATUSES.index(example["inspection_status"]),
|
||||
)
|
||||
object_role = st.text_input(
|
||||
"논리 객체 역할",
|
||||
value=example["object_role"],
|
||||
max_chars=64,
|
||||
placeholder="예: GAME_USER_MASTER",
|
||||
)
|
||||
inspection_note = st.text_area(
|
||||
"검토 메모",
|
||||
value=example["inspection_note"],
|
||||
height=100,
|
||||
max_chars=4_000,
|
||||
)
|
||||
submitted = st.form_submit_button("Few-shot 변경 저장", type="primary")
|
||||
|
||||
if not submitted:
|
||||
return
|
||||
try:
|
||||
store.update_vector_example(
|
||||
example_id=example["example_id"],
|
||||
source_case_id=selected_question.question_code,
|
||||
question=question,
|
||||
answer_sql=answer_sql,
|
||||
answer_text=answer_text,
|
||||
reference_status=reference_status,
|
||||
reference_kind=reference_kind,
|
||||
target_type=target_type,
|
||||
object_role=object_role,
|
||||
inspection_status=inspection_status,
|
||||
inspection_note=inspection_note,
|
||||
verified_by=str(st.session_state.get(PORTAL_AUTH_USER_KEY) or "PORTAL_OPERATOR"),
|
||||
)
|
||||
except QaHistoryStoreError as exc:
|
||||
st.error(str(exc))
|
||||
return
|
||||
st.success("Few-shot 예제와 검색용 embedding을 저장했습니다.")
|
||||
st.rerun()
|
||||
|
||||
|
||||
def _apply_console_theme(profile: AppProfile) -> None:
|
||||
apply_console_theme(st, profile)
|
||||
|
||||
@@ -7515,7 +7667,9 @@ def main() -> None:
|
||||
'<div id="kb-main-tabs-anchor" style="scroll-margin-top: 0.75rem;"></div>',
|
||||
unsafe_allow_html=True,
|
||||
)
|
||||
architecture_tab, scenario_tab = st.tabs(["아키텍처", "시나리오"])
|
||||
architecture_tab, scenario_tab, few_shot_tab = st.tabs(
|
||||
["아키텍처", "시나리오", "Few-shot 관리"]
|
||||
)
|
||||
with architecture_tab:
|
||||
_render_architecture_tab()
|
||||
|
||||
@@ -7617,6 +7771,13 @@ def main() -> None:
|
||||
height=0,
|
||||
)
|
||||
|
||||
with few_shot_tab:
|
||||
_render_few_shot_management_tab(
|
||||
qa_questions,
|
||||
qa_history_store,
|
||||
qa_store_error,
|
||||
)
|
||||
|
||||
if not submitted:
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user