| |
|
|
| import streamlit as st |
| import os |
| import asyncio |
| import re |
| from groq import Groq |
| from prompts import ( |
| INSIGHT_CHAIN_SYSTEM_PROMPT, |
| INSIGHT_CHAIN_USER_PROMPT, |
| RESPONSE_SYSTEM_PROMPT |
| ) |
| from validators.factory import ValidatorFactory |
| from ai_coder_app import AICoderApp |
| from utils import run_async |
|
|
| |
| client = Groq( |
| api_key=os.environ.get("GROQ_API_KEY") |
| ) |
|
|
| |
| ai_coder_app = AICoderApp(client) |
|
|
| |
| st.title("気づきの連鎖AIチャット(モード分離版)") |
| st.markdown("質問や問題を入力すると、AIが気づきの連鎖プロセスで深く考察し、選択したモードに応じた回答を提供します。") |
|
|
| |
| if "messages" not in st.session_state: |
| st.session_state.messages = [] |
| if "last_prompt" not in st.session_state: |
| st.session_state.last_prompt = None |
| if "feedback_count" not in st.session_state: |
| st.session_state.feedback_count = 0 |
| if "app_mode" not in st.session_state: |
| st.session_state.app_mode = "normal" |
| if "context_preserved" not in st.session_state: |
| st.session_state.context_preserved = False |
|
|
| |
| if hasattr(ai_coder_app, "current_mode"): |
| ai_coder_app.current_mode = st.session_state.app_mode |
|
|
| |
| for message in st.session_state.messages: |
| with st.chat_message(message["role"]): |
| st.markdown(message["content"]) |
|
|
| |
| with st.sidebar: |
| st.title("モード設定") |
| |
| |
| mode_options = { |
| "normal": "通常モード(一般的な質問応答)", |
| "implementation": "実装モード(アイデア→設計→実装)", |
| "verification": "検証修正モード(コード検証と修正)", |
| "error_resolution": "エラー解決モード(エラー診断と修正)" |
| } |
| |
| selected_mode = st.selectbox( |
| "動作モード", |
| options=list(mode_options.keys()), |
| format_func=lambda x: mode_options[x], |
| index=list(mode_options.keys()).index(st.session_state.app_mode) |
| ) |
| |
| |
| if selected_mode != st.session_state.app_mode: |
| |
| if not st.session_state.context_preserved and len(st.session_state.messages) > 0: |
| st.session_state.context_preserved = True |
| print(f"DEBUG: モード変更時のコンテキスト保存: {st.session_state.app_mode} -> {selected_mode}") |
| |
| st.session_state.app_mode = selected_mode |
| ai_coder_app.current_mode = selected_mode |
| |
| |
| mode_change_message = f"モードを「{mode_options[selected_mode]}」に変更しました。" |
| |
| |
| mode_descriptions = { |
| "normal": "通常の質問応答モードです。一般的な質問や議論に適しています。", |
| "implementation": "アイデアから設計と実装を生成するモードです。新しい機能の開発に適しています。", |
| "verification": "コードを検証して問題点を修正するモードです。既存コードの品質向上に適しています。", |
| "error_resolution": "エラーメッセージから問題を診断・修正するモードです。デバッグに適しています。" |
| } |
| |
| mode_change_message += f"\n\n{mode_descriptions[selected_mode]}" |
| |
| |
| context_info = "" |
| if st.session_state.app_mode == "verification" and len(st.session_state.messages) > 0: |
| |
| last_assistant_message = next((msg["content"] for msg in reversed(st.session_state.messages) |
| if msg["role"] == "assistant"), None) |
| |
| |
| if last_assistant_message and "```" in last_assistant_message: |
| context_info = "\n\n前回の実装結果を検証する場合は、「前回のコードを検証してください」と入力してください。" |
| |
| mode_change_message += context_info |
| |
| |
| st.session_state.messages.append({"role": "assistant", "content": mode_change_message}) |
| |
| |
| st.markdown(f"### {mode_options[selected_mode]}の設定") |
| |
| |
| if selected_mode == "normal" or selected_mode == "implementation": |
| thought_depth_help = "値が大きいほど、より深い考察が行われます" if selected_mode == "normal" else "値が大きいほど、実装前の分析の深さが増します" |
| thought_depth = st.slider("思考の深さ", min_value=1, max_value=5, value=3, |
| help=thought_depth_help) |
| |
| if selected_mode == "implementation": |
| physics_validation = st.checkbox("物理シミュレーション検証", value=False, |
| help="物理シミュレーションの正確性と安定性を検証します") |
| |
| elif selected_mode == "verification": |
| physics_validation = st.checkbox("物理シミュレーション検証", value=False, |
| help="物理シミュレーションの正確性と安定性を検証します") |
| |
| dependency_resolution = st.checkbox("依存性解決", value=True, |
| help="暗黙的な依存関係を検出し、必要なインポートを追加します") |
| |
| test_generation = st.checkbox("テスト生成", value=False, |
| help="包括的なテストケースを自動生成します") |
| |
| edge_case_validation = st.checkbox("エッジケース検証", value=True, |
| help="境界条件とエッジケースを特定し対処します") |
| |
| elif selected_mode == "error_resolution": |
| |
| pass |
| |
| |
| with st.expander("詳細設定", expanded=False): |
| max_retries = st.slider("修正ループ最大回数", min_value=1, max_value=3, value=2, |
| help="コード生成のフィードバックと改善ループの最大回数") |
| |
| focus_area = st.selectbox("重点検証項目", |
| options=["全般", "コードの完全性", "エラーハンドリング", "物理的正確性", "エッジケース処理"], |
| help="検証時に特に重視する項目") |
| |
| |
| preserve_context = st.checkbox("会話履歴を引き継ぐ", value=True, |
| help="モード切替時に会話履歴を引き継ぎます") |
| |
| if not preserve_context and st.button("会話履歴をクリア", help="現在の会話履歴をすべて削除します"): |
| st.session_state.messages = [] |
| st.session_state.context_preserved = False |
| st.rerun() |
| |
| |
| debug_mode = st.checkbox("デバッグモード", value=False) |
| if debug_mode: |
| if hasattr(ai_coder_app, "last_insight_chain_result") and ai_coder_app.last_insight_chain_result: |
| st.markdown("### 気づきの連鎖AIの生成結果") |
| st.markdown(ai_coder_app.last_insight_chain_result) |
| |
| if hasattr(ai_coder_app, "last_design_doc") and ai_coder_app.last_design_doc: |
| st.markdown("### 設計書") |
| st.markdown(ai_coder_app.last_design_doc) |
| |
| if hasattr(ai_coder_app, "last_verification_result") and ai_coder_app.last_verification_result: |
| st.markdown("### コード検証結果") |
| st.markdown(ai_coder_app.last_verification_result.get("verification_summary", "")) |
| |
| if hasattr(ai_coder_app, "context") and ai_coder_app.context: |
| st.markdown("### モード別コンテキスト") |
| st.write(f"保存されているモード: {list(ai_coder_app.context.keys())}") |
| for mode, ctx in ai_coder_app.context.items(): |
| if ctx: |
| st.markdown(f"**{mode}モード**:") |
| st.write(f"- 保存データ: {list(ctx.keys())}") |
| |
| if st.session_state.last_prompt: |
| st.markdown("### 最終プロンプト") |
| st.markdown(st.session_state.last_prompt) |
|
|
| |
| mode_placeholders = { |
| "normal": "質問や議論したいトピックを入力してください", |
| "implementation": "実装したい機能やアイデアを入力してください", |
| "verification": "検証・修正したいコードを入力してください", |
| "error_resolution": "発生したエラーメッセージとコードを入力してください" |
| } |
|
|
| |
| previous_code_keywords = [ |
| "前回のコード", "前の実装結果", "前のコード", "先ほどのコード", "さっきのコード", |
| "previous code", "generated code", "above code" |
| ] |
|
|
| |
| if prompt := st.chat_input(mode_placeholders.get(selected_mode, "質問や問題を入力してください")): |
| |
| if selected_mode == "verification" and any(keyword in prompt.lower() for keyword in previous_code_keywords) and not "```" in prompt: |
| |
| last_assistant_message = next((msg["content"] for msg in reversed(st.session_state.messages) |
| if msg["role"] == "assistant"), None) |
| |
| if last_assistant_message: |
| |
| code_blocks = re.findall(r"```(\w*)\n([\s\S]*?)\n```", last_assistant_message) |
| |
| if code_blocks: |
| |
| enhanced_prompt = prompt + "\n\n" |
| for lang, code in code_blocks: |
| lang = lang or "python" |
| enhanced_prompt += f"```{lang}\n{code}\n```\n\n" |
| |
| prompt = enhanced_prompt |
| print("DEBUG: 前回のコードブロックを検証用に追加しました") |
| |
| |
| st.session_state.messages.append({"role": "user", "content": prompt}) |
| |
| |
| if st.session_state.last_prompt != prompt: |
| st.session_state.feedback_count = 0 |
| ai_coder_app.feedback_count = 0 |
| |
| st.session_state.last_prompt = prompt |
| |
| |
| with st.chat_message("user"): |
| st.markdown(prompt) |
| |
| |
| with st.chat_message("assistant"): |
| message_placeholder = st.empty() |
| message_placeholder.markdown("考え中...") |
| |
| try: |
| |
| settings = { |
| "app_mode": selected_mode, |
| |
| "thought_depth": thought_depth if 'thought_depth' in locals() else 3, |
| |
| |
| "physics_validation": physics_validation if 'physics_validation' in locals() else False, |
| |
| |
| "dependency_resolution": dependency_resolution if 'dependency_resolution' in locals() else True, |
| "test_generation": test_generation if 'test_generation' in locals() else False, |
| "edge_case_validation": edge_case_validation if 'edge_case_validation' in locals() else True, |
| |
| |
| "max_retries": max_retries if 'max_retries' in locals() else 2, |
| "focus_area": focus_area if 'focus_area' in locals() else "全般", |
| "preserve_context": preserve_context if 'preserve_context' in locals() else True |
| } |
| |
| |
| with st.spinner("AIが応答を生成中..."): |
| final_result = run_async(ai_coder_app.process_user_input(prompt, settings)) |
| |
| |
| message_placeholder.markdown(final_result) |
| |
| |
| st.session_state.messages.append({"role": "assistant", "content": final_result}) |
| |
| except Exception as e: |
| message_placeholder.markdown(f"エラーが発生しました: {str(e)}") |
| st.error(f"API呼び出し中にエラーが発生しました: {str(e)}") |
|
|
| |
| with st.sidebar: |
| if selected_mode == "verification": |
| if st.button("コード再検証", help="現在表示されているコードを再度検証し、さらなる改善を行います"): |
| if st.session_state.messages and len(st.session_state.messages) > 0: |
| |
| last_assistant_message = next((msg["content"] for msg in reversed(st.session_state.messages) |
| if msg["role"] == "assistant"), None) |
| |
| if last_assistant_message: |
| |
| st.session_state.messages.append({ |
| "role": "user", |
| "content": "このコードをさらに検証して改善してください。" |
| }) |
| |
| |
| st.rerun() |