Spaces:
Running
Running
| import gradio as gr | |
| import uuid | |
| from datetime import datetime | |
| import pandas as pd | |
| from model_handler import ModelHandler | |
| from config import CHAT_MODEL_SPECS, LING_1T | |
| from recommand_config import RECOMMENDED_INPUTS | |
| from ui_components.model_selector import create_model_selector | |
| def create_chat_tab(): | |
| model_handler = ModelHandler() | |
| conversation_store = gr.BrowserState(default_value=[], storage_key="ling_conversation_history") | |
| current_conversation_id = gr.BrowserState(default_value=None, storage_key="ling_current_conversation_id") | |
| def get_history_df(history): | |
| if not history: | |
| return pd.DataFrame({'ID': [], '对话': []}) | |
| df = pd.DataFrame(history) | |
| return df[['id', 'title']].rename(columns={'id': 'ID', 'title': '对话'}) | |
| def handle_new_chat(history, current_conv_id=None): | |
| # Try to find the current conversation | |
| current_convo = next((c for c in history if c["id"] == current_conv_id), None) if history else None | |
| # If current conversation exists and is empty, reuse it | |
| if current_convo and not current_convo.get("messages", []): | |
| return ( | |
| current_conv_id, | |
| history, | |
| [], | |
| gr.update(value=get_history_df(history)) | |
| ) | |
| conv_id = str(uuid.uuid4()) | |
| new_convo = { | |
| "id": conv_id, "title": "(新对话)", | |
| "messages": [], "timestamp": datetime.now().isoformat() | |
| } | |
| updated_history = [new_convo] + (history or []) | |
| return ( | |
| conv_id, | |
| updated_history, | |
| [], | |
| gr.update(value=get_history_df(updated_history)) | |
| ) | |
| def load_conversation_from_df(df: pd.DataFrame, evt: gr.SelectData, history): | |
| if evt.index is None: | |
| return None, [] | |
| selected_id = df.iloc[evt.index[0]]['ID'] | |
| for convo in history: | |
| if convo["id"] == selected_id: | |
| return selected_id, convo["messages"] | |
| # Fallback to new chat if something goes wrong | |
| new_id, _, new_msgs, _ = handle_new_chat(history) | |
| return new_id, new_msgs | |
| with gr.Row(equal_height=False, elem_id="indicator-chat-tab"): | |
| with gr.Column(scale=1): | |
| new_chat_btn = gr.Button("➕ 新对话") | |
| history_df = gr.DataFrame( | |
| value=get_history_df(conversation_store.value), | |
| headers=["ID", "对话记录"], | |
| datatype=["str", "str"], | |
| interactive=False, | |
| visible=True, | |
| column_widths=["0%", "99%"] | |
| ) | |
| with gr.Column(scale=4): | |
| chatbot = gr.Chatbot(height=500, type='messages') | |
| with gr.Row(): | |
| textbox = gr.Textbox(placeholder="输入消息...", container=False, scale=7) | |
| submit_btn = gr.Button("发送", scale=1) | |
| gr.Markdown("### 推荐对话") | |
| recommended_dataset = gr.Dataset( | |
| components=[gr.Textbox(visible=False)], | |
| samples=[[item["task"]] for item in RECOMMENDED_INPUTS], | |
| label="推荐场景", headers=["选择一个场景试试"], | |
| ) | |
| with gr.Column(scale=1): | |
| model_dropdown, model_description_markdown = create_model_selector( | |
| model_specs=CHAT_MODEL_SPECS, | |
| default_model_constant=LING_1T | |
| ) | |
| system_prompt_textbox = gr.Textbox(label="系统提示词", lines=5, placeholder="输入系统提示词...") | |
| temperature_slider = gr.Slider(minimum=0, maximum=1.0, value=0.7, step=0.1, label="温度参数") | |
| # --- Event Handlers --- # | |
| # The change handler is now encapsulated within create_model_selector | |
| def on_select_recommendation(evt: gr.SelectData, history, current_conv_id): | |
| selected_task = evt.value[0] | |
| item = next((i for i in RECOMMENDED_INPUTS if i["task"] == selected_task), None) | |
| if not item: return gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update() | |
| new_id, new_history, new_messages, history_df_update = handle_new_chat(history, current_conv_id) | |
| return ( | |
| new_id, new_history, | |
| gr.update(value=item["model"]), | |
| gr.update(value=item["system_prompt"]), | |
| gr.update(value=item["temperature"]), | |
| gr.update(value=item["user_message"]), | |
| history_df_update, | |
| new_messages | |
| ) | |
| recommended_dataset.select(on_select_recommendation, inputs=[conversation_store, current_conversation_id], outputs=[current_conversation_id, conversation_store, model_dropdown, system_prompt_textbox, temperature_slider, textbox, history_df, chatbot], show_progress="none") | |
| def chat_stream(conv_id, history, model_display_name, message, chat_history, system_prompt, temperature): | |
| if not message: | |
| yield chat_history | |
| return | |
| model_constant = next((k for k, v in CHAT_MODEL_SPECS.items() if v["display_name"] == model_display_name), LING_1T) | |
| response_generator = model_handler.get_response(model_constant, message, chat_history, system_prompt, temperature) | |
| for history_update in response_generator: | |
| yield history_update | |
| def on_chat_stream_complete(conv_id, history, final_chat_history): | |
| current_convo = next((c for c in history if c["id"] == conv_id), None) | |
| if not current_convo: | |
| return history, gr.update() | |
| if len(final_chat_history) > len(current_convo["messages"]) and current_convo["title"] == "(新对话)": | |
| user_message = final_chat_history[-2]["content"] if len(final_chat_history) > 1 else final_chat_history[0]["content"] | |
| current_convo["title"] = user_message[:50] | |
| current_convo["messages"] = final_chat_history | |
| current_convo["timestamp"] = datetime.now().isoformat() | |
| history = sorted([c for c in history if c["id"] != conv_id] + [current_convo], key=lambda x: x["timestamp"], reverse=True) | |
| return history, gr.update(value=get_history_df(history)) | |
| submit_btn.click( | |
| chat_stream, | |
| [current_conversation_id, conversation_store, model_dropdown, textbox, chatbot, system_prompt_textbox, temperature_slider], | |
| [chatbot] | |
| ).then( | |
| on_chat_stream_complete, | |
| [current_conversation_id, conversation_store, chatbot], | |
| [conversation_store, history_df] | |
| ) | |
| textbox.submit( | |
| chat_stream, | |
| [current_conversation_id, conversation_store, model_dropdown, textbox, chatbot, system_prompt_textbox, temperature_slider], | |
| [chatbot] | |
| ).then( | |
| on_chat_stream_complete, | |
| [current_conversation_id, conversation_store, chatbot], | |
| [conversation_store, history_df] | |
| ) | |
| new_chat_btn.click(handle_new_chat, inputs=[conversation_store, current_conversation_id], outputs=[current_conversation_id, conversation_store, chatbot, history_df]) | |
| history_df.select(load_conversation_from_df, inputs=[history_df, conversation_store], outputs=[current_conversation_id, chatbot]) | |
| return conversation_store, current_conversation_id, history_df, chatbot |