import gradio as gr from config import CHAT_SYSTEM_PROMPT_PLACEHOLDER, CHAT_MODEL_SPECS from models import get_model_response import logging import copy logger = logging.getLogger(__name__) # --- Backend Logic --- def handle_chat(message, history, system_prompt, temperature, model_id): """处理聊天消息提交的核心函数""" logger.debug(f"handle_chat 输入: message={message}, history={history}, system_prompt={system_prompt}, temperature={temperature}, model_id={model_id}") if history is None: history = [] history = copy.deepcopy(history) history.append((message, "")) # 从 spec 中获取用于显示的名称 model_display_name = CHAT_MODEL_SPECS.get(model_id, {}).get("display_name", model_id) is_first_chunk = True for chunk in get_model_response(model_id, history, system_prompt, temperature): if is_first_chunk: # 在第一个块前加上模型名称 history[-1] = (message, f"**{model_display_name}**\n\n" + chunk) is_first_chunk = False else: history[-1] = (message, history[-1][1] + chunk) yield copy.deepcopy(history), "" # --- UI Event Handlers --- def handle_model_change(model_id): """当用户切换模型时,更新UI""" spec = CHAT_MODEL_SPECS[model_id] scenarios = spec.get("prompt_scenarios", []) # 默认加载第一个场景 if scenarios: first_scenario = scenarios[0] scenario_titles = [[s["title"]] for s in scenarios] message_examples = [[m] for m in first_scenario["message_examples"]] system_prompt_value = first_scenario["system_prompt"] else: # 兼容没有场景的情况 scenario_titles = [] message_examples = [] system_prompt_value = "" return ( gr.update(value=spec["description"]), gr.update(samples=scenario_titles), gr.update(value=system_prompt_value), gr.update(samples=message_examples) ) def handle_scenario_selection(model_id, evt: gr.SelectData): """当用户从场景数据集中选择一个场景时,更新UI""" logger.debug(f"--- Scenario Selection Event ---") logger.debug(f"Selected event value: {evt.value}") logger.debug(f"Type of event value: {type(evt.value)}") # 修正:从列表中提取字符串 selected_title = evt.value[0] if isinstance(evt.value, list) and evt.value else None if not selected_title: logger.error("Selected event value is not a valid list or is empty.") return gr.update(), gr.update() spec = CHAT_MODEL_SPECS[model_id] scenarios = spec.get("prompt_scenarios", []) available_titles = [s['title'] for s in scenarios] logger.debug(f"Available scenario titles for model '{model_id}': {available_titles}") selected_scenario = next((s for s in scenarios if s["title"] == selected_title), None) if selected_scenario: logger.debug(f"Found matching scenario: '{selected_title}'") system_prompt_value = selected_scenario["system_prompt"] message_examples = [[m] for m in selected_scenario["message_examples"]] return gr.update(value=system_prompt_value), gr.update(samples=message_examples) logger.warning(f"No matching scenario found for title: '{selected_title}'") # 如果找不到场景,则不更新 return gr.update(), gr.update() # --- UI Creation --- def create_chat_tab(): """创建并返回聊天标签页的所有Gradio组件""" # 从配置中提取模型信息用于UI展示 # choices 是一个 (display_name, model_id) 的元组列表 model_choices = [(spec["display_name"], model_id) for model_id, spec in CHAT_MODEL_SPECS.items()] default_model_id = list(CHAT_MODEL_SPECS.keys())[0] default_spec = CHAT_MODEL_SPECS[default_model_id] default_scenarios = default_spec.get("prompt_scenarios", []) with gr.TabItem("聊天", id="chat_tab"): with gr.Row(): with gr.Column(scale=3): chatbot = gr.Chatbot( label="聊天窗口", bubble_full_width=False, height=500, value=[(None, "Hello! I'm Ling. Try selecting a scenario and a message example below to get started.")] ) with gr.Row(): chat_input = gr.Textbox(placeholder="Ask me anything...", label="输入框", show_label=False, scale=4) send_button = gr.Button("发送", variant="primary", scale=1) # 新的场景化示例区域 with gr.Accordion("✨ 试试这些场景...", open=True): # 场景选择器 scenario_selector = gr.Dataset( components=[gr.Textbox(visible=False)], samples=[[s["title"]] for s in default_scenarios], label="系统提示示例", headers=["选择一个角色或任务来开始:"], ) # 消息示例 message_examples_display = gr.Dataset( components=[chat_input], samples=[[m] for m in default_scenarios[0]["message_examples"]] if default_scenarios else [], label="消息示例", headers=["然后,试试这些具体问题:"], ) with gr.Column(scale=1): model_selector = gr.Radio( choices=model_choices, label="选择模型", value=default_model_id ) model_description = gr.Markdown(default_spec["description"]) system_prompt = gr.Textbox( label="System Prompt", lines=8, placeholder=CHAT_SYSTEM_PROMPT_PLACEHOLDER, value=default_scenarios[0]["system_prompt"] if default_scenarios else "" ) temperature_slider = gr.Slider(minimum=0.0, maximum=2.0, value=1.0, step=0.1, label="Temperature") # --- Event Listeners --- model_selector.change( fn=handle_model_change, inputs=[model_selector], outputs=[model_description, scenario_selector, system_prompt, message_examples_display] ) scenario_selector.select( fn=handle_scenario_selection, inputs=[model_selector], outputs=[system_prompt, message_examples_display] ) message_examples_display.click( fn=lambda value: value[0], inputs=[message_examples_display], outputs=[chat_input] ) return { "chatbot": chatbot, "chat_input": chat_input, "send_button": send_button, "system_prompt": system_prompt, "temperature_slider": temperature_slider, "model_selector": model_selector, }