Spaces:
Sleeping
Sleeping
import streamlit as st | |
import os | |
from chat_manager import ChatManager | |
from llm_client import LLMClient | |
from i18n_utils import I18nManager | |
from ui_components import render_message, render_sidebar, show_notification | |
from config import Config | |
from prompt_template import PromptTemplateManager | |
# Page configuration | |
st.set_page_config( | |
page_title="MyChatMe", | |
page_icon="🤖", | |
layout="wide", | |
initial_sidebar_state="expanded", | |
menu_items={ | |
"Get Help": None, | |
"Report a bug": None, | |
"About": "MyChatMe - Multilingual AI Chat Application" | |
} | |
) | |
# Initialize session state | |
if "chat_manager" not in st.session_state: | |
st.session_state.chat_manager = ChatManager() | |
if "llm_client" not in st.session_state: | |
st.session_state.llm_client = LLMClient() | |
if "i18n" not in st.session_state: | |
st.session_state.i18n = I18nManager() | |
if "sidebar_state" not in st.session_state: | |
st.session_state.sidebar_state = "expanded" | |
if "test_mode" not in st.session_state: | |
st.session_state.test_mode = False | |
if "template_manager" not in st.session_state: | |
st.session_state.template_manager = PromptTemplateManager() | |
def render_template_manager(i18n): | |
"""プロンプトテンプレート管理セクションを表示""" | |
with st.expander(i18n.get_text("prompt_templates")): | |
# テンプレート一覧表示と選択 | |
templates = st.session_state.template_manager.list_templates() | |
if templates: | |
template_names = [f"{t['name']} ({t['created_at']})" for t in templates] | |
selected_template = st.selectbox( | |
i18n.get_text("select_template"), | |
[""] + template_names, | |
key="template_selector" | |
) | |
if selected_template: | |
template = templates[template_names.index(selected_template) - 1] | |
# 選択したテンプレートの内容をフォームに表示 | |
new_template_name = st.text_input( | |
i18n.get_text("template_name"), | |
value=template["name"], | |
key=f"edit_name_{template['id']}" | |
) | |
new_template_content = st.text_area( | |
i18n.get_text("template_content"), | |
value=template["content"], | |
key=f"edit_content_{template['id']}" | |
) | |
new_template_description = st.text_input( | |
i18n.get_text("template_description"), | |
value=template.get("description", ""), | |
key=f"edit_description_{template['id']}" | |
) | |
col1, col2 = st.columns(2) | |
with col1: | |
if st.button(i18n.get_text("delete_template")): | |
if st.session_state.template_manager.delete_template(template["id"]): | |
show_notification(i18n.get_text("template_deleted"), "success") | |
# 削除後にセッション状態をクリア | |
if "template_selector" in st.session_state: | |
del st.session_state.template_selector | |
st.rerun() | |
with col2: | |
if st.button(i18n.get_text("save_template"), key=f"save_button_{template['id']}"): | |
try: | |
if st.session_state.template_manager.update_template( | |
template["id"], | |
name=new_template_name, | |
content=new_template_content, | |
description=new_template_description | |
): | |
show_notification(i18n.get_text("template_saved"), "success") | |
# 更新後にセッション状態をクリア | |
if "template_selector" in st.session_state: | |
del st.session_state.template_selector | |
st.rerun() | |
else: | |
show_notification(i18n.get_text("template_error"), "error") | |
except Exception as e: | |
show_notification(f"{i18n.get_text('template_error')}: {str(e)}", "error") | |
# テンプレートが存在しない場合または新規作成モードの場合 | |
if not templates or not selected_template: | |
new_template_name = st.text_input( | |
i18n.get_text("template_name"), | |
key="new_template_name" | |
) | |
new_template_content = st.text_area( | |
i18n.get_text("template_content"), | |
key="new_template_content" | |
) | |
new_template_description = st.text_input( | |
i18n.get_text("template_description"), | |
key="new_template_description" | |
) | |
if st.button(i18n.get_text("save_template"), key="save_new_template"): | |
try: | |
if st.session_state.template_manager.add_template( | |
new_template_name, | |
new_template_content, | |
new_template_description | |
): | |
show_notification(i18n.get_text("template_saved"), "success") | |
# 保存後にセッション状態をクリア | |
for key in list(st.session_state.keys()): | |
if key.startswith("new_template_"): | |
del st.session_state[key] | |
st.rerun() | |
else: | |
show_notification(i18n.get_text("template_error"), "error") | |
except Exception as e: | |
show_notification(f"{i18n.get_text('template_error')}: {str(e)}", "error") | |
def main(): | |
# アプリケーション起動情報 | |
print("\n[MyChatMe] アプリケーションを起動中...") | |
print(f" Version: {Config.VERSION}") | |
print(f" 言語: {st.session_state.i18n._current_language}") | |
print(" コンポーネントを初期化中...") | |
i18n = st.session_state.i18n | |
chat_manager = st.session_state.chat_manager | |
llm_client = st.session_state.llm_client | |
st.title(i18n.get_text("app_title")) | |
# Check API keys | |
if not Config.get_openai_key(): | |
show_notification(i18n.get_text("error_missing_key") + " (OpenAI)", "warning") | |
if not Config.get_openrouter_key(): | |
show_notification(i18n.get_text("error_missing_key") + " (OpenRouter)", "warning") | |
# Sidebar | |
language, model = render_sidebar(i18n, chat_manager) | |
# Add test mode toggle in sidebar for development | |
with st.sidebar: | |
st.markdown("---") | |
st.header(i18n.get_text("developer_mode")) | |
test_mode = st.checkbox(i18n.get_text("enable_error_test"), value=st.session_state.test_mode) | |
if test_mode != st.session_state.test_mode: | |
st.session_state.test_mode = test_mode | |
llm_client.set_test_mode(test_mode) | |
if test_mode: | |
show_notification(i18n.get_text("error_test_enabled"), "info") | |
else: | |
show_notification(i18n.get_text("error_test_disabled"), "info") | |
# Update language | |
if language == "English" and i18n._current_language != "en": | |
i18n.set_language("en") | |
st.rerun() | |
elif language == "日本語" and i18n._current_language != "ja": | |
i18n.set_language("ja") | |
st.rerun() | |
# プロンプトテンプレート管理を表示 | |
render_template_manager(i18n) | |
# System prompt | |
system_prompt = st.text_area( | |
i18n.get_text("system_prompt"), | |
value=i18n.get_text("default_system_prompt"), | |
key="system_prompt" | |
) | |
# Chat history selection | |
if chat_manager.history: | |
selected_chat = st.selectbox( | |
i18n.get_text("chat_history"), | |
["New Chat"] + [f"Chat {session.created_at}" for session in chat_manager.history] | |
) | |
if selected_chat != "New Chat": | |
chat_id = chat_manager.history[ | |
[f"Chat {session.created_at}" for session in chat_manager.history].index(selected_chat) | |
].id | |
chat_manager.load_chat(chat_id) | |
# Display chat messages | |
for message in chat_manager.get_messages(include_system=False): | |
render_message(message["role"], message["content"]) | |
# Chat input | |
if prompt := st.chat_input(i18n.get_text("chat_placeholder")): | |
# Add user message | |
chat_manager.add_message("user", prompt) | |
render_message("user", prompt) | |
try: | |
# Get AI response based on selected model | |
messages = chat_manager.get_messages() | |
response = None | |
# Model selection logic | |
model_map = { | |
"OpenRouter-Auto": llm_client.chat_auto, | |
"OpenAI": llm_client.chat_openai, | |
"Claude-3.5": llm_client.chat_claude, | |
"Gemini-2.0": llm_client.chat_gemini, | |
"deepseek-chat": llm_client.chat_deepseek | |
} | |
if model in model_map: | |
try: | |
response = model_map[model](messages) | |
except Exception as e: | |
error_msg = str(e) | |
if "Rate limit exceeded" in error_msg: | |
if "provider" in error_msg: | |
show_notification(f"{i18n.get_text('error_rate_limit')} ({error_msg})", "warning") | |
else: | |
show_notification(i18n.get_text("error_rate_limit"), "warning") | |
elif "API key" in error_msg: | |
if model == "OpenAI": | |
show_notification(i18n.get_text("error_model_switch_openai"), "error") | |
else: | |
show_notification(i18n.get_text("error_model_switch_openrouter"), "error") | |
elif "network" in error_msg.lower(): | |
show_notification(i18n.get_text("error_network"), "error") | |
else: | |
show_notification(f"{i18n.get_text('error_model_switch')}: {error_msg}", "error") | |
return | |
else: | |
show_notification(f"Invalid model selection: {model}", "error") | |
return | |
if response: | |
# Add AI response | |
chat_manager.add_message("assistant", response) | |
render_message("assistant", response) | |
# Generate and update context summary periodically | |
if len(chat_manager.current_session.messages) % 5 == 0: # Every 5 messages | |
try: | |
summary = llm_client.generate_context_summary(chat_manager.current_session.messages) | |
chat_manager.update_context_summary(summary) | |
except Exception as e: | |
print(f"Failed to generate context summary: {str(e)}") | |
# Keep sidebar expanded after chat | |
st.session_state.sidebar_state = "expanded" | |
except Exception as e: | |
show_notification(f"{i18n.get_text('error_api_call')}: {str(e)}", "error") | |
# Clear chat button | |
if st.button(i18n.get_text("clear_chat")): | |
chat_manager.clear_current_chat() | |
st.rerun() | |
if __name__ == "__main__": | |
print("========================================") | |
print("MyChatMe - 多言語AIチャットアプリケーション") | |
print("========================================") | |
main() | |