developer-lunark's picture
Upload folder using huggingface_hub
7b7257a verified
"""Single Chat νƒ­ UI"""
import gradio as gr
from typing import Any
from models.model_registry import get_all_models, get_model_info
from characters import get_character_loader, build_system_prompt
from utils import parse_thinking_response, format_thinking_for_display
def create_chat_tab(
model_manager: Any = None,
use_mock: bool = False,
):
"""Single Chat νƒ­ 생성"""
# 데이터 λ‘œλ”
char_loader = get_character_loader()
# λͺ¨λΈ λͺ©λ‘
all_models = get_all_models()
model_choices = [(f"{get_model_info(m).get('description', m)}", m) for m in all_models]
# 캐릭터 λͺ©λ‘
characters = char_loader.get_character_names()
# ============================================================
# UI ꡬ성
# ============================================================
gr.Markdown("## 단일 λͺ¨λΈ μ±„νŒ…")
gr.Markdown("μ„ νƒν•œ λͺ¨λΈκ³Ό μΊλ¦­ν„°λ‘œ λŒ€ν™”λ₯Ό λ‚˜λˆ λ³΄μ„Έμš”.")
with gr.Row():
with gr.Column(scale=1):
model_dropdown = gr.Dropdown(
choices=model_choices,
value=all_models[0] if all_models else None,
label="λͺ¨λΈ 선택",
)
with gr.Column(scale=1):
character_dropdown = gr.Dropdown(
choices=characters,
value=characters[0] if characters else None,
label="캐릭터 선택",
)
# μ±„νŒ… μ˜μ—­
chatbot = gr.Chatbot(
label="λŒ€ν™”",
height=400,
type="messages",
)
with gr.Accordion("Thinking Process (λ§ˆμ§€λ§‰ 응닡)", open=False):
thinking_display = gr.Markdown("*(응닡 생성 ν›„ ν‘œμ‹œλ©λ‹ˆλ‹€)*")
with gr.Row():
user_input = gr.Textbox(
label="λ©”μ‹œμ§€ μž…λ ₯",
placeholder="λ©”μ‹œμ§€λ₯Ό μž…λ ₯ν•˜μ„Έμš”...",
lines=2,
scale=4,
)
send_btn = gr.Button("전솑", variant="primary", scale=1)
with gr.Row():
clear_btn = gr.Button("λŒ€ν™” μ΄ˆκΈ°ν™”")
metadata_display = gr.Markdown("")
# ============================================================
# 이벀트 ν•Έλ“€λŸ¬
# ============================================================
def respond(
model_id: str,
character: str,
message: str,
history: list,
):
"""응닡 생성"""
if not message.strip():
return history, "", "*(λ©”μ‹œμ§€λ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”)*", ""
# λŒ€ν™” νžˆμŠ€ν† λ¦¬ ꡬ성
messages = []
for msg in history:
if msg["role"] == "user":
messages.append({"role": "user", "content": msg["content"]})
elif msg["role"] == "assistant":
# Thinking μ œκ±°ν•œ 클린 μ‘λ‹΅λ§Œ νžˆμŠ€ν† λ¦¬μ—
_, clean = parse_thinking_response(msg["content"])
messages.append({"role": "assistant", "content": clean})
messages.append({"role": "user", "content": message})
system_prompt = build_system_prompt(character)
# Mock λ˜λŠ” μ‹€μ œ μΆ”λ‘ 
if use_mock or model_manager is None:
response_full = f"<think>\n{character}λ‘œμ„œ 생각해보면...\n</think>\n\nμ•ˆλ…•~ λ°˜κ°€μ›Œ! (Mock Response)"
meta = {"latency_s": 0.5, "output_tokens": 30}
else:
try:
response_full, meta = model_manager.generate_response(
model_id, messages, system_prompt
)
except Exception as e:
response_full = f"*Error: {str(e)}*"
meta = {"latency_s": 0, "output_tokens": 0}
# Thinking νŒŒμ‹±
thinking, clean_response = parse_thinking_response(response_full)
# νžˆμŠ€ν† λ¦¬ μ—…λ°μ΄νŠΈ
history.append({"role": "user", "content": message})
history.append({"role": "assistant", "content": response_full})
# 메타데이터
meta_str = f"⏱️ {meta.get('latency_s', 0):.2f}s | {meta.get('output_tokens', 0)} tokens"
return (
history,
"", # μž…λ ₯ μ΄ˆκΈ°ν™”
format_thinking_for_display(thinking) if thinking else "*No thinking*",
meta_str,
)
def clear_chat():
"""λŒ€ν™” μ΄ˆκΈ°ν™”"""
return [], "", "*(응닡 생성 ν›„ ν‘œμ‹œλ©λ‹ˆλ‹€)*", ""
# ============================================================
# 이벀트 바인딩
# ============================================================
send_btn.click(
fn=respond,
inputs=[model_dropdown, character_dropdown, user_input, chatbot],
outputs=[chatbot, user_input, thinking_display, metadata_display],
)
user_input.submit(
fn=respond,
inputs=[model_dropdown, character_dropdown, user_input, chatbot],
outputs=[chatbot, user_input, thinking_display, metadata_display],
)
clear_btn.click(
fn=clear_chat,
outputs=[chatbot, user_input, thinking_display, metadata_display],
)