iT邦幫忙

2025 iThome 鐵人賽

DAY 29
1

另一個檔案

今天跟昨天一樣來放完整的程式碼,因為功能也都介紹得差不多了。
明天就是最後一天了,好欸
https://ithelp.ithome.com.tw/upload/images/20251013/20177921lR3dtHpphv.png

import customtkinter
import google.generativeai as genai
import threading
import queue
import re
import requests
from opencc import OpenCC
import tkinter.filedialog as filedialog
import tkinter as tk
from pathlib import Path
import markdown
from tkinter import font
import time

import os
from dotenv import load_dotenv
# LangChain imports
from langchain.agents import initialize_agent, AgentType
from langchain.tools import Tool
from langchain.llms.base import LLM
from langchain.schema import Generation, LLMResult
from typing import List, Optional, Any
from pydantic import BaseModel, Field
load_dotenv()
api_key=os.getenv('API_KEY')
# ====================================================================
# Custom Gemini LLM wrapper for LangChain
# ====================================================================
# Base URL for local API server (configurable via env)
LOCAL_API_BASE = os.environ.get("LOCAL_API_BASE", "http://127.0.0.1:8000")


class GeminiLLM(LLM):
    """Custom LLM wrapper for Google Gemini"""
    
    # 使用 Pydantic Field 來定義模型屬性
    api_key: str = Field(...)
    model_name: str = Field(default="models/gemini-2.5-flash")
    opencc_converter: Any = Field(default=None)
    
    class Config:
        """Pydantic 配置"""
        arbitrary_types_allowed = True
    
    def __init__(self, api_key: str, **kwargs):
        # 初始化 OpenCC 轉換器
        opencc_converter = OpenCC('s2t')
        
        # 調用父類初始化,傳入所有必要字段
        super().__init__(
            api_key=api_key, 
            opencc_converter=opencc_converter,
            **kwargs
        )
        
        # 初始化 Gemini
        genai.configure(api_key=api_key)
        self._model = genai.GenerativeModel(model_name=self.model_name)
        self._chat = self._model.start_chat(history=[])
    
    @property
    def _llm_type(self) -> str:
        return "gemini"
    
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        try:
            response = self._chat.send_message(prompt)
            return self.opencc_converter.convert(response.text)
        except Exception as e:
            return f"錯誤: {str(e)}"
    
    def _generate(self, prompts: List[str], stop: Optional[List[str]] = None) -> LLMResult:
        generations = []
        for prompt in prompts:
            text = self._call(prompt, stop)
            generations.append([Generation(text=text)])
        return LLMResult(generations=generations)

# ====================================================================
# LangChain Tools Definition
# ====================================================================
class SystemTools:
    def __init__(self, app_instance=None):
        self.opencc_converter = OpenCC('s2t')
        self.app_instance = app_instance  # 引用主應用程式實例
        # 初始化Gemini用於內容生成
        api_key = os.environ.get("GEMINI_API_KEY") or (getattr(app_instance, "gemini_llm", None) and getattr(app_instance.gemini_llm, "api_key", None))
        if not api_key:
            raise RuntimeError("未找到 GEMINI_API_KEY。請設定環境變數後再執行。")
        genai.configure(api_key=api_key)
        model_name = os.environ.get("GEMINI_MODEL") or (getattr(app_instance, "gemini_llm", None) and getattr(app_instance.gemini_llm, "model_name", "models/gemini-2.5-flash")) or "models/gemini-2.5-flash"
        self.content_model = genai.GenerativeModel(model_name)
    
    def check_available_content_tool(self, input_text: str = "") -> str:
        """檢查當前可用的內容狀態"""
        print(f"[DEBUG] ===== check_available_content_tool 被調用了! =====")
        print(f"[DEBUG] app_instance 型別: {type(self.app_instance)}")
        print(f"[DEBUG] app_instance hasattr last_analysis_result: {hasattr(self.app_instance, 'last_analysis_result')}")
        
        if hasattr(self.app_instance, 'last_analysis_result'):
            print(f"[DEBUG] last_analysis_result 長度: {len(self.app_instance.last_analysis_result) if self.app_instance.last_analysis_result else 0}")
            print(f"[DEBUG] last_analysis_result 前100字: {self.app_instance.last_analysis_result[:100] if self.app_instance.last_analysis_result else 'None'}")
        
        status_info = []
        latest_time = 0
        latest_type = ""
        
        # 檢查生成內容
        print(f"[DEBUG] 檢查生成內容...")
        if (hasattr(self.app_instance, 'last_generated_content') and 
            self.app_instance.last_generated_content and
            self.app_instance.last_generated_content.strip()):
            gen_time = getattr(self.app_instance, 'last_generated_time', 0)
            content_preview = self.app_instance.last_generated_content[:100].replace('\n', ' ')
            status_info.append(f"✅ 生成內容: {len(self.app_instance.last_generated_content)}字符 (預覽: {content_preview}...)")
            print(f"[DEBUG] 找到生成內容,時間戳: {gen_time}, 長度: {len(self.app_instance.last_generated_content)}")
            if gen_time > latest_time:
                latest_time = gen_time
                latest_type = "生成內容"
        else:
            print(f"[DEBUG] 沒有生成內容")
        
        # 檢查分析結果
        print(f"[DEBUG] 檢查分析結果...")
        if (hasattr(self.app_instance, 'last_analysis_result') and 
            self.app_instance.last_analysis_result and
            self.app_instance.last_analysis_result.strip()):
            analysis_time = getattr(self.app_instance, 'last_analysis_time', 0)
            content_preview = self.app_instance.last_analysis_result[:100].replace('\n', ' ')
            status_info.append(f"✅ 分析結果: {len(self.app_instance.last_analysis_result)}字符 (預覽: {content_preview}...)")
            print(f"[DEBUG] 找到分析結果,時間戳: {analysis_time}, 長度: {len(self.app_instance.last_analysis_result)}")
            if analysis_time > latest_time:
                latest_time = analysis_time
                latest_type = "分析結果"
        else:
            print(f"[DEBUG] 沒有分析結果")
        
        # 檢查上傳檔案
        print(f"[DEBUG] 檢查上傳檔案...")
        if (hasattr(self.app_instance, 'uploaded_file_content') and 
            self.app_instance.uploaded_file_content and
            self.app_instance.uploaded_file_content.strip()):
            upload_time = getattr(self.app_instance, 'last_upload_time', 0)
            content_preview = self.app_instance.uploaded_file_content[:100].replace('\n', ' ')
            filename = getattr(self.app_instance, 'last_uploaded_filename', '未知檔案')
            status_info.append(f"✅ 上傳檔案({filename}): {len(self.app_instance.uploaded_file_content)}字符 (預覽: {content_preview}...)")
            print(f"[DEBUG] 找到上傳檔案,時間戳: {upload_time}, 長度: {len(self.app_instance.uploaded_file_content)}")
            if upload_time > latest_time:
                latest_time = upload_time
                latest_type = "上傳檔案內容"
        else:
            print(f"[DEBUG] 沒有上傳檔案")
        
        print(f"[DEBUG] 最終狀態信息數量: {len(status_info)}")
        
        if not status_info:
            return "❌ 目前沒有可用的內容。請先生成內容、分析檔案或上傳檔案。"
        
        result = "📋 當前可用內容狀態:\n\n" + "\n".join(status_info)
        if latest_type:
            result += f"\n\n🔥 最新內容: {latest_type}"
            result += f"\n💡 提示: 使用「將已生成內容寫入Word」可以將最新內容寫入Word"
        
        print(f"[DEBUG] 回傳結果: {result[:200]}...")
        return result
    
    def generate_content_tool(self, topic: str) -> str:
        """生成指定主題的創意內容"""
        print(f"[DEBUG] ===== generate_content_tool 被調用了! =====")
        print(f"[DEBUG] 收到的主題: '{topic}'")
        
        try:
            # 解析用戶需求
            if not topic.strip():
                return "請提供要生成內容的主題。"
            
            # 根據關鍵詞判斷內容類型
            content_type = "文章"
            if "心得" in topic or "感想" in topic or "評價" in topic:
                content_type = "心得感想"
            elif "故事" in topic or "小說" in topic:
                content_type = "故事"
            elif "報告" in topic or "分析" in topic:
                content_type = "分析報告"
            elif "介紹" in topic:
                content_type = "介紹文章"
            elif "信" in topic or "信件" in topic:
                content_type = "信件"
            
            # 生成詳細提示
            if content_type == "心得感想":
                prompt = f"""請為以下主題寫一篇詳細的心得感想(約300-500字):

主題:{topic}

請包含以下要素:
1. 個人的感受和印象
2. 具體的例子或情節
3. 深層的思考和啟發
4. 結論和總結

請用繁體中文書寫,語調要自然親切。"""
            else:
                prompt = f"""請為以下主題生成一篇詳細的{content_type}(約300-500字):

主題:{topic}

請確保內容:
1. 結構完整清晰
2. 內容豐富有趣
3. 語言流暢自然
4. 符合主題要求

請用繁體中文書寫。"""
            
            print(f"[DEBUG] 準備使用Gemini生成內容,content_type: {content_type}")
            print(f"[DEBUG] 生成的prompt長度: {len(prompt)}")
            
            # 使用Gemini生成內容
            response = self.content_model.generate_content(prompt)
            generated_content = response.text
            
            print(f"[DEBUG] Gemini回傳內容長度: {len(generated_content)}")
            print(f"[DEBUG] Gemini回傳內容前100字: {generated_content[:100]}...")
            
            # 轉換為繁體中文
            generated_content = self.opencc_converter.convert(generated_content)
            
            print(f"[DEBUG] 轉換繁體中文後長度: {len(generated_content)}")
            
            # 保存生成的內容供後續使用
            if self.app_instance:
                import time
                self.app_instance.last_generated_content = generated_content
                self.app_instance.last_generated_time = time.time()
                print(f"[DEBUG] 已保存生成的內容,長度: {len(generated_content)},時間戳: {self.app_instance.last_generated_time}")
            
            print(f"[DEBUG] 準備回傳完整內容,長度: {len(generated_content)}")
            return generated_content
            
        except Exception as e:
            print(f"[DEBUG] generate_content_tool發生錯誤: {type(e).__name__}: {e}")
            # 當API配額用完時,提示用戶
            if "quota" in str(e).lower() or "429" in str(e):
                return f"內容生成功能暫時不可用(API配額已用完)。請稍後重試或考慮升級API方案。原始錯誤:{str(e)}"
            else:
                return f"生成內容時發生錯誤: {e}"
    
    def open_paint_tool(self, input_text: str) -> str:
        """開啟小畫家應用程式"""
        print(f"[DEBUG] ===== open_paint_tool 被調用了! =====")
        print(f"[DEBUG] 準備調用API: {LOCAL_API_BASE}/open-paint")
        try:
            response = requests.post(f"{LOCAL_API_BASE}/open-paint")
            response.raise_for_status()
            result = response.json()
            print(f"[DEBUG] API回應成功: {result}")
            return result["message"]
        except requests.exceptions.ConnectionError:
            print(f"[DEBUG] API連線失敗")
            return "錯誤:無法連線到本地 API 服務。請確認伺服器已啟動。"
        except Exception as e:
            print(f"[DEBUG] API調用發生錯誤: {e}")
            return f"開啟小畫家時發生錯誤: {e}"
    
    def open_notepad_tool(self, input_text: str) -> str:
        """開啟記事本應用程式"""
        try:
            response = requests.post(f"{LOCAL_API_BASE}/open-notepad")
            response.raise_for_status()
            result = response.json()
            return result["message"]
        except requests.exceptions.ConnectionError:
            return "錯誤:無法連線到本地 API 服務。請確認伺服器已啟動。"
        except Exception as e:
            return f"開啟記事本時發生錯誤: {e}"
    
    def open_blank_word_tool(self, input_text: str) -> str:
        """純粹開啟空白的 Word 應用程式,不寫入任何內容"""
        print(f"[DEBUG] ===== open_blank_word_tool 被調用了! =====")
        print(f"[DEBUG] 準備調用API: {LOCAL_API_BASE}/open-blank-word")
        try:
            response = requests.post(f"{LOCAL_API_BASE}/open-blank-word")
            response.raise_for_status()
            result = response.json()
            print(f"[DEBUG] API回應成功: {result}")
            return result["message"]
        except requests.exceptions.ConnectionError:
            print(f"[DEBUG] API連線失敗")
            return "錯誤:無法連線到本地 API 服務。請確認伺服器已啟動。"
        except Exception as e:
            print(f"[DEBUG] API調用發生錯誤: {e}")
            return f"開啟空白Word時發生錯誤: {e}"
    
    def open_word_tool(self, content: str) -> str:
        """開啟 Word 並輸入指定內容"""
        print(f"[DEBUG] open_word_tool 被調用,參數: '{content}'")
        
        # 使用統一的時間檢查機制
        import time
        current_time = time.time()
        if hasattr(self, '_last_word_operation_time'):
            time_diff = current_time - self._last_word_operation_time
            if time_diff < 1.5:  # 縮短到1.5秒,使用統一機制
                print(f"[DEBUG] Word在{time_diff:.1f}秒前剛開啟過,避免重複調用")
                return "Word剛開啟過,請稍候..."
        
        # 設置最後操作時間
        self._last_word_operation_time = current_time
        
        try:
            # 檢查內容來源優先順序:
            # 1. 如果有具體內容,直接使用
            # 2. 如果是空內容或要求解答/分析結果,按時間戳檢查最新內容
            if (not content.strip() or 
                content.strip() in ["", "解答", "分析結果", "答案"] or
                "解答" in content and len(content.strip()) < 10):
                
                print(f"[DEBUG] 檢測到空內容或請求解答,檢查所有可用內容...")
                
                latest_time = 0
                latest_content = ""
                latest_source = ""
                
                # 檢查分析結果
                if (hasattr(self.app_instance, 'last_analysis_result') and 
                    self.app_instance.last_analysis_result.strip()):
                    analysis_time = getattr(self.app_instance, 'last_analysis_time', 0)
                    if analysis_time > latest_time:
                        latest_time = analysis_time
                        latest_content = self.app_instance.last_analysis_result
                        latest_source = "分析結果"
                
                # 檢查生成內容
                if (hasattr(self.app_instance, 'last_generated_content') and 
                    self.app_instance.last_generated_content.strip()):
                    gen_time = getattr(self.app_instance, 'last_generated_time', 0)
                    if gen_time > latest_time:
                        latest_time = gen_time
                        latest_content = self.app_instance.last_generated_content
                        latest_source = "生成內容"
                
                # 檢查上傳檔案
                if (hasattr(self.app_instance, 'uploaded_file_content') and 
                    self.app_instance.uploaded_file_content.strip()):
                    upload_time = getattr(self.app_instance, 'last_upload_time', 0)
                    if upload_time > latest_time:
                        latest_time = upload_time
                        latest_content = self.app_instance.uploaded_file_content
                        latest_source = "上傳檔案內容"
                
                if latest_content:
                    content = latest_content
                    print(f"[DEBUG] open_word_tool: 使用最新的{latest_source},時間戳: {latest_time},長度: {len(content)}")
                else:
                    print(f"[DEBUG] open_word_tool: 沒有找到任何保存的內容,使用預設內容")
                    content = "您沒有指定內容,這是預設文字。"
            
            # 直接調用實際執行函數
            result = self._actually_open_word(content)
            return result
        finally:
            # 無需清除標誌,因為我們使用時間戳機制
            pass
    
    def _actually_open_word(self, content: str) -> str:
        """實際執行Word開啟的內部函數"""
        print(f"[DEBUG] ===== _actually_open_word 被調用了! =====")
        print(f"[DEBUG] 收到的參數: '{content[:100]}...'")
        
        # 統一使用同一個時間檢查機制,避免衝突
        current_time = time.time()
        if hasattr(self.app_instance.system_tools, '_last_word_operation_time'):
            time_diff = current_time - self.app_instance.system_tools._last_word_operation_time
            if time_diff < 1.5:  # 縮短到1.5秒,防止過度阻擋
                print(f"[DEBUG] Word在{time_diff:.1f}秒前剛開啟過,避免重複調用")
                return "Word剛開啟過,請稍候..."
        
        # 記錄操作時間
        self.app_instance.system_tools._last_word_operation_time = current_time
        
        # 檢查是否有指定內容,如果沒有則檢查是否有分析結果可用
        if (not content.strip() or 
            content.strip() == "您沒有指定內容,這是預設文字。" or
            "沒有預設" in content or 
            "請提供" in content or 
            "我目前沒有" in content or
            len(content.strip()) < 50):  # 如果內容太短,可能是預設回應
            if (hasattr(self.app_instance, 'last_analysis_result') and 
                self.app_instance.last_analysis_result.strip()):
                content = self.app_instance.last_analysis_result
                print(f"[DEBUG] 使用保存的分析結果作為內容,長度: {len(content)}")
            else:
                content = "您沒有指定內容,這是預設文字。"
                print(f"[DEBUG] 沒有找到分析結果,使用預設內容")
        
        try:
            data = {"content": content}
            print(f"[DEBUG] 準備發送的數據長度: {len(str(data))}")
            print(f"[DEBUG] 準備調用API: {LOCAL_API_BASE}/open-word")
            
            response = requests.post(f"{LOCAL_API_BASE}/open-word", json=data, timeout=30)
            
            print(f"[DEBUG] API響應狀態碼: {response.status_code}")
            print(f"[DEBUG] API響應內容: {response.text}")
            
            response.raise_for_status()
            result = response.json()
            
            # 檢查API返回的狀態
            if result.get("status") == "error":
                return f"API錯誤: {result.get('message', '未知錯誤')}"
            
            return result.get("message", "Word操作完成,但沒有返回詳細信息")
        except requests.exceptions.ConnectionError as e:
            return f"錯誤:無法連線到本地 API 服務 (127.0.0.1:8000)。請確認伺服器已啟動。詳細錯誤: {e}"
        except requests.exceptions.Timeout as e:
            return f"錯誤:API請求超時。詳細錯誤: {e}"
        except requests.exceptions.HTTPError as e:
            return f"錯誤:HTTP錯誤 {response.status_code}。響應內容: {response.text}"
        except Exception as e:
            return f"開啟 Word 時發生未預期錯誤: {type(e).__name__}: {e}"
    
    def write_to_word_tool(self, topic: str) -> str:
        """生成內容並寫入Word"""
        print(f"[DEBUG] ===== write_to_word_tool 被調用了! =====")
        print(f"[DEBUG] 收到的主題: '{topic}'")
        
        # 使用統一的時間檢查機制
        import time
        current_time = time.time()
        if hasattr(self, '_last_word_operation_time'):
            time_diff = current_time - self._last_word_operation_time
            if time_diff < 1.5:  # 使用統一機制
                print(f"[DEBUG] Word在{time_diff:.1f}秒前剛開啟過,避免重複調用")
                return "Word剛開啟過,內容已經寫入完成。"
        
        try:
            # 先生成內容
            content = self.generate_content_tool(topic)
            print(f"[DEBUG] 生成的內容長度: {len(content)}")
            
            # 然後開啟Word並寫入內容
            result = self.open_word_tool(content)
            print(f"[DEBUG] Word操作結果: {result}")
            
            # 保留所有分析結果,不再清除任何內容
            # 這樣各種專家模式都能正常工作
            print(f"[DEBUG] 保留所有分析結果,支援多次Word操作")
            
            return f"已生成'{topic}'的內容並寫入Word。{result}"
            
        except Exception as e:
            error_msg = f"寫入內容到Word時發生錯誤: {type(e).__name__}: {e}"
            print(f"[DEBUG] {error_msg}")
            return error_msg
    
    def write_generated_to_word_tool(self, input_text: str = "") -> str:
        """將最近生成的內容寫入Word"""
        print(f"[DEBUG] ===== write_generated_to_word_tool 被調用了! =====")
        
        try:
            content = ""
            source = ""
            latest_time = 0
            
            # 檢查各種內容的時間戳,選擇最新的
            if (hasattr(self.app_instance, 'last_generated_content') and 
                self.app_instance.last_generated_content.strip()):
                gen_time = getattr(self.app_instance, 'last_generated_time', 0)
                if gen_time > latest_time:
                    latest_time = gen_time
                    content = self.app_instance.last_generated_content
                    source = "生成內容"
                    print(f"[DEBUG] 找到生成內容,時間戳: {gen_time}, 長度: {len(content)}")
                
            if (hasattr(self.app_instance, 'last_analysis_result') and 
                self.app_instance.last_analysis_result.strip()):
                analysis_time = getattr(self.app_instance, 'last_analysis_time', 0)
                if analysis_time > latest_time:
                    latest_time = analysis_time
                    content = self.app_instance.last_analysis_result
                    source = "分析結果"
                    print(f"[DEBUG] 找到分析結果,時間戳: {analysis_time}, 長度: {len(content)}")
                
            if (hasattr(self.app_instance, 'uploaded_file_content') and 
                self.app_instance.uploaded_file_content.strip()):
                upload_time = getattr(self.app_instance, 'last_upload_time', 0)
                if upload_time > latest_time:
                    latest_time = upload_time
                    content = self.app_instance.uploaded_file_content
                    source = "上傳檔案內容"
                    print(f"[DEBUG] 找到上傳檔案內容,時間戳: {upload_time}, 長度: {len(content)}")
            
            print(f"[DEBUG] 選擇最新內容: {source},時間戳: {latest_time}")
            
            if content.strip():
                # 直接調用_actually_open_word避免重複的時間檢查
                result = self._actually_open_word(content)
                print(f"[DEBUG] Word操作結果: {result}")
                
                return f"已將{source}寫入Word。{result}"
            else:
                print(f"[DEBUG] 沒有找到任何可寫入的內容")
                return "沒有找到可寫入的內容。請先生成內容、分析檔案或上傳檔案,然後再寫入Word。"
                
        except Exception as e:
            error_msg = f"將內容寫入Word時發生錯誤: {type(e).__name__}: {e}"
            print(f"[DEBUG] {error_msg}")
            return error_msg

    def modify_word_tool(self, content: str) -> str:
        """修改已開啟的 Word 文件內容"""
        try:
            data = {"content": content if content.strip() else "您沒有指定內容,這是預設文字。"}
            response = requests.post(f"{LOCAL_API_BASE}/modify-word", json=data)
            response.raise_for_status()
            result = response.json()
            return result["message"]
        except requests.exceptions.ConnectionError:
            return "錯誤:無法連線到本地 API 服務。請確認伺服器已啟動。"
        except Exception as e:
            return f"修改 Word 時發生錯誤: {e}"
    
    def save_word_tool(self, filename: str) -> str:
        """儲存 Word 文件"""
        print(f"[DEBUG] ===== save_word_tool 被調用了! =====")
        print(f"[DEBUG] 收到的檔名: '{filename}'")
        try:
            # 檢查是否提供檔名
            if not filename.strip():
                print(f"[DEBUG] 檔名為空,詢問用戶")
                return "請問要將檔案儲存為什麼名稱?"
            
            # 檢查檔名是否是一般性詞彙,而非真實檔名
            generic_names = ["文件", "檔案", "word文件", "word檔案", "內容", "文字"]
            if filename.strip().lower() in generic_names:
                print(f"[DEBUG] 檔名是一般性詞彙,詢問用戶")
                return "請問要將檔案儲存為什麼名稱?"
            
            print(f"[DEBUG] 準備發送API請求,檔名: '{filename.strip()}'")
            data = {"filename": filename.strip()}
            response = requests.post(f"{LOCAL_API_BASE}/save-word", json=data)
            response.raise_for_status()
            result = response.json()
            print(f"[DEBUG] API響應狀態碼: {response.status_code}")
            print(f"[DEBUG] API響應內容: {result}")
            return result["message"]
        except requests.exceptions.ConnectionError:
            return "錯誤:無法連線到本地 API 服務。請確認伺服器已啟動。"
        except Exception as e:
            return f"儲存 Word 時發生錯誤: {e}"
    
    def check_word_status_tool(self, input_text: str) -> str:
        """檢查Word應用程式狀態"""
        try:
            response = requests.post(f"{LOCAL_API_BASE}/check-word-status")
            response.raise_for_status()
            result = response.json()
            return result["message"]
        except requests.exceptions.ConnectionError:
            return "錯誤:無法連線到本地 API 服務。請確認伺服器已啟動。"
        except Exception as e:
            return f"檢查Word狀態時發生錯誤: {e}"
    
    
    def upload_file_tool(self, file_path: str) -> str:
        """上傳檔案並分兩階段處理"""
        print(f"[DEBUG] ===== upload_file_tool 被調用了! =====")
        print(f"[DEBUG] 檔案路徑: '{file_path}'")
        
        try:
            if not file_path or not Path(file_path).exists():
                return "檔案路徑無效或檔案不存在"
            
            filename = Path(file_path).name
            print(f"[DEBUG] 準備上傳檔案: {filename}")
            
            with open(file_path, 'rb') as file:
                files = {'file': (filename, file, 'application/octet-stream')}
                print(f"[DEBUG] 發送請求到API...")
                response = requests.post(f"{LOCAL_API_BASE}/upload-file", files=files, timeout=30)
                
                print(f"[DEBUG] API響應狀態碼: {response.status_code}")
                print(f"[DEBUG] API響應內容: {response.text[:200]}...")
                
                response.raise_for_status()
                result = response.json()
                
                if result['status'] == 'success':
                    # 儲存檔案內容供後續使用(統一變數名稱)
                    if self.app_instance:
                        import time
                        self.app_instance.last_uploaded_file_content = result['content']
                        self.app_instance.uploaded_file_content = result['content']  # 統一變數名稱
                        self.app_instance.last_uploaded_filename = filename
                        self.app_instance.last_upload_time = time.time()
                        print(f"[DEBUG] 已保存上傳檔案內容,長度: {len(result['content'])},時間戳: {self.app_instance.last_upload_time}")
                        # 設置等待用戶回覆的標記
                        self.app_instance.waiting_for_file_action = True
                    
                    return f"""✅ 檔案上傳成功!

📁 檔案名稱: {filename}
📊 檔案大小: {len(result['content'])} 字元  
📝 檔案類型: {Path(filename).suffix or '未知'}

請問您想要做什麼?
• 分析重點 - 找出檔案中的關鍵信息
• 解題 - 解答檔案中的問題
• 寫心得 - 根據檔案內容寫感想
• 翻譯 - 翻譯檔案內容
• 總結 - 提供內容摘要
• 詳細分析 - 深入分析檔案內容

請直接告訴我您的需求!"""
                else:
                    return f"檔案上傳失敗: {result['message']}"
        except requests.exceptions.ConnectionError:
            return "錯誤:無法連線到本地 API 服務。請確認伺服器已啟動。"
        except Exception as e:
            return f"檔案上傳時發生錯誤: {e}"
    
    def analyze_file_content_tool(self, analysis_type: str = "詳細分析", expert_type: str = "學術分析專家", expert_prompt: str = "") -> str:
        """分析已上傳的檔案內容,根據AI智能判斷的專家身份進行分析"""
        try:
            # 檢查是否有已上傳的檔案
            if not self.app_instance or not hasattr(self.app_instance, 'last_uploaded_file_content'):
                return "請先上傳檔案再進行分析。"
            
            file_content = self.app_instance.last_uploaded_file_content
            filename = getattr(self.app_instance, 'last_uploaded_filename', '未知檔案')
            
            if not file_content.strip():
                return "檔案內容為空,無法進行分析。"
            
            # 根據專家類型和分析類型選擇不同的提示詞
            if "數學專家" in expert_type and ("解題" in analysis_type or "解答" in analysis_type or "求解" in analysis_type):
                analysis_prompt = f"""{expert_prompt}

請仔細分析並解決以下檔案中的數學題目或問題:

檔案名稱:{filename}
檔案內容:
{file_content}

請以數學專家的身份提供:
1. 問題識別和理解
2. 詳細的解題步驟
3. 計算過程(如果需要)
4. 最終答案
5. 驗證或檢查(如果適用)
6. 相關的數學概念解釋

請用繁體中文回應,步驟要清晰易懂,展現專業的數學知識。"""

            elif "文學專家" in expert_type:
                analysis_prompt = f"""{expert_prompt}

請根據以下檔案內容寫出專業的文學分析:

檔案名稱:{filename}
檔案內容:
{file_content}

請以文學專家的身份提供:
1. 作品主題和文學意義
2. 寫作技巧和文學手法分析
3. 人物形象和情節發展
4. 語言風格和修辭特色
5. 個人的專業見解和評價
6. 文學價值和啟發

請用繁體中文回應,展現深度的文學洞察力。"""

            elif "翻譯專家" in expert_type:
                analysis_prompt = f"""{expert_prompt}

請將以下檔案內容進行專業翻譯:

檔案名稱:{filename}
檔案內容:
{file_content}

請以翻譯專家的身份提供:
1. 準確且自然的翻譯
2. 重要術語的翻譯說明
3. 文化背景的適當處理
4. 語言風格的保持

請提供高品質的專業翻譯。"""

            elif "信息整理專家" in expert_type and ("總結" in analysis_type or "摘要" in analysis_type or "重點" in analysis_type):
                analysis_prompt = f"""{expert_prompt}

請對以下檔案進行專業的信息整理:

檔案名稱:{filename}
檔案內容:
{file_content}

請以信息整理專家的身份提供:
1. 核心主題和關鍵概念
2. 重要信息的結構化整理
3. 關鍵數據和事實
4. 需要特別注意的要點
5. 邏輯清晰的總結

請用繁體中文回應,以專業的方式進行信息整理。"""

            elif "科學專家" in expert_type:
                analysis_prompt = f"""{expert_prompt}

請對以下科學相關檔案進行專業分析:

檔案名稱:{filename}
檔案內容:
{file_content}

請以科學專家的身份提供:
1. 科學概念和理論背景
2. 實驗設計和方法分析
3. 數據解釋和結論評估
4. 科學意義和應用價值
5. 可能的改進建議
6. 相關的科學知識擴展

請用繁體中文回應,展現嚴謹的科學分析能力。"""

            elif "商業分析專家" in expert_type:
                analysis_prompt = f"""{expert_prompt}

請對以下商業相關檔案進行專業分析:

檔案名稱:{filename}
檔案內容:
{file_content}

請以商業分析專家的身份提供:
1. 商業模式和策略分析
2. 市場環境和競爭分析
3. 財務和營運評估
4. 風險和機會識別
5. 專業的商業建議
6. 未來發展趨勢預測

請用繁體中文回應,展現專業的商業洞察力。"""

            else:
                # 預設學術分析專家模式
                analysis_prompt = f"""{expert_prompt or "你是一位學術分析專家,具備深厚的研究能力和批判性思維。"}

請對以下檔案進行深入的學術分析:

檔案名稱:{filename}
檔案內容:
{file_content}

請以學術分析專家的身份提供:
1. 內容主題和背景分析
2. 詳細的學術觀點探討
3. 關鍵信息和重點識別
4. 批判性思考和評價
5. 學術價值和意義
6. 相關領域的知識連結

請用繁體中文回應,展現深度的學術分析能力。"""

            response = self.content_model.generate_content(analysis_prompt)
            analysis_result = response.text
            
            # 轉換為繁體中文
            analysis_result = self.opencc_converter.convert(analysis_result)
            
            # 保存分析結果到app_instance,供後續Word操作使用
            if self.app_instance:
                import time
                self.app_instance.last_analysis_result = analysis_result
                self.app_instance.last_analysis_time = time.time()
                print(f"[DEBUG] 已保存分析結果到app_instance,長度: {len(analysis_result)},時間戳: {self.app_instance.last_analysis_time}")
            
            return f"📋 {expert_type}分析結果:{filename}\n\n{analysis_result}"
                
        except Exception as e:
            # 當API配額用完時,提示用戶
            if "quota" in str(e).lower() or "429" in str(e):
                return f"檔案分析功能暫時不可用(API配額已用完)。請稍後重試或考慮升級API方案。原始錯誤:{str(e)}"
            else:
                return f"分析檔案內容時發生錯誤: {e}"

# ====================================================================
# Main LangChain Agent App
# ====================================================================
class LangChainAgentApp(customtkinter.CTk):
    def __init__(self):
        super().__init__()
        
        # 基本窗口設置
        self.title("LangChain Agent 助手")
        self.geometry("1200x700")
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=1)
        
        # 設置主題
        customtkinter.set_appearance_mode("dark")
        customtkinter.set_default_color_theme("blue")
        
        # 初始化變量
        self.chat_history = []
        self.message_queue = queue.Queue()
        self.agent = None
        self.system_tools = None
        
        # 檔案處理相關變量
        self.waiting_for_file_action = False
        self.last_uploaded_file_content = ""
        self.last_uploaded_filename = ""
        self.last_analysis_result = ""  # 保存最近的分析結果
        
        # Word處理防重複標誌
        self._word_opening = False
        
        # 初始化 LangChain 組件
        self._initialize_langchain()
        
        # 建立GUI
        self._create_gui()
        
        # 開始訊息處理迴圈
        self.check_queue()
        
        # 歡迎訊息
        self.message_queue.put(("系統", """🎯 LangChain Agent 助手已啟動!

我可以協助您:
📄 開啟應用程式 (記事本、小畫家、Word等)
🔧 檔案處理 (上傳、分析各種檔案格式)
 內容生成 (創意寫作、心得感想等)
⚙️ 系統操作

請輸入問題或使用上傳檔案功能開始!"""))
    
    def _initialize_langchain(self):
        """初始化 LangChain 組件"""
        try:
            # Gemini API 設定
            api_key = os.getenv('API_KEY')
            
            # 創建自定義 LLM
            self.gemini_llm = GeminiLLM(api_key=api_key, model_name=os.environ.get("GEMINI_MODEL", "models/gemini-2.5-flash"))
            
            # 初始化系統工具
            self.system_tools = SystemTools(app_instance=self)
            
            # 定義工具
            tools = [
                Tool(
                    name="內容生成工具",
                    func=self.system_tools.generate_content_tool,
                    description="生成創意內容,如文章、心得、故事等。輸入主題或要求即可。"
                ),
                Tool(
                    name="開啟小畫家",
                    func=self.system_tools.open_paint_tool,
                    description="開啟Windows小畫家應用程式"
                ),
                Tool(
                    name="開啟記事本",
                    func=self.system_tools.open_notepad_tool,
                    description="開啟Windows記事本應用程式"
                ),
                Tool(
                    name="開啟空白Word",
                    func=self.system_tools.open_blank_word_tool,
                    description="純粹開啟一個空白的Word應用程式。用於:用戶只是想開啟Word但不需要立即寫入內容的情況。當用戶說'開啟Word'、'打開Word'、'開Word'而沒有提到要寫入內容時使用。"
                ),
                Tool(
                    name="開啟Word並輸入內容",
                    func=self.system_tools.open_word_tool,
                    description="開啟Word並輸入指定的內容。用於:1)將特定內容直接寫入Word;2)將之前的分析結果/解答寫入Word(傳入空字符串會自動使用最近的分析結果)。如果有具體內容要寫入,請將該內容作為參數傳入。當用戶明確要求寫入內容時使用。"
                ),
                Tool(
                    name="將已生成內容寫入Word",
                    func=self.system_tools.write_generated_to_word_tool,
                    description="將最近的內容寫入Word,包括:1)生成的內容(小說、文章等);2)分析結果(檔案分析、解題答案等);3)翻譯結果;4)上傳檔案內容。用於當用戶說'把剛才的內容寫入Word'、'將解題結果寫入Word'、'把分析結果輸入Word'等。系統會自動選擇最新的內容。"
                ),
                Tool(
                    name="寫內容到Word",
                    func=self.system_tools.write_to_word_tool,
                    description="根據指定主題重新生成內容並寫入Word。用於創作新的文章、小說、報告等。不適用於寫入已有的內容或分析結果。當用戶說'把生成的XX寫入Word'時,應該使用'開啟Word並輸入內容'工具,並將已生成的內容作為參數傳入。"
                ),
                Tool(
                    name="修改Word內容",
                    func=self.system_tools.modify_word_tool,
                    description="修改已開啟的Word文件內容"
                ),
                Tool(
                    name="儲存Word文件",
                    func=self.system_tools.save_word_tool,
                    description="儲存Word文件。如果用戶只說'存檔'而沒有指定檔名,應該詢問'請問要將檔案儲存為什麼名稱?',並將使用者後續輸入的文字作為檔案名稱儲存。如果用戶說'存檔,檔名叫做XXX',則使用XXX作為檔案名稱儲存。"
                ),
                Tool(
                    name="檢查Word狀態",
                    func=self.system_tools.check_word_status_tool,
                    description="檢查Word應用程式的當前狀態"
                ),
                Tool(
                    name="檢查內容狀態",
                    func=self.system_tools.check_available_content_tool,
                    description="檢查當前系統中有哪些內容可以寫入Word,包括生成內容、分析結果、上傳檔案等。當用戶詢問內容狀態或無法確定有什麼內容可寫入時使用。"
                ),
                Tool(
                    name="檔案上傳分析",
                    func=self.system_tools.upload_file_tool,
                    description="上傳檔案並顯示上傳成功訊息,然後詢問用戶要做什麼。支援多種檔案格式如Word、PDF、文字檔等。"
                ),
                Tool(
                    name="檔案內容分析",
                    func=self.system_tools.analyze_file_content_tool,
                    description="對已上傳的檔案進行各種分析。可以進行:詳細分析、總結摘要、提取重點、翻譯內容、寫心得感想等。請在參數中指定分析類型,如'總結'、'重點'、'翻譯'、'心得'或'詳細分析'。"
                ),
                
            ]
            
            # 創建自定義錯誤處理函數
            def custom_error_handler(error) -> str:
                """自定義錯誤處理函數,嘗試解析並執行動作"""
                # 將錯誤對象轉換為字符串
                error_msg = str(error)
                print(f"[DEBUG] 解析錯誤,嘗試自定義處理: {error_msg}")
                print(f"[DEBUG] 錯誤類型: {type(error)}")
                
                # 首先檢查是否是應用程式開啟請求,忽略LLM可能編造的觀察結果
                # 只要錯誤訊息中包含Action請求,就實際執行工具
                if "Action: 開啟小畫家" in error_msg:
                    print(f"[DEBUG] 檢測到小畫家開啟請求,直接執行真正的工具")
                    print(f"[DEBUG] 錯誤訊息內容: {error_msg[:200]}...")
                    try:
                        print(f"[DEBUG] 準備調用 open_paint_tool")
                        result = self.system_tools.open_paint_tool("")
                        print(f"[DEBUG] open_paint_tool 返回結果: {result}")
                        return f"小畫家應用程式已成功開啟,您可以開始繪圖了。實際結果:{result}"
                    except Exception as e:
                        print(f"[DEBUG] 開啟小畫家時發生錯誤: {e}")
                        return f"開啟小畫家時發生錯誤: {e}"
                
                if "Action: 開啟記事本" in error_msg:
                    print(f"[DEBUG] 檢測到記事本開啟請求,直接執行真正的工具")
                    try:
                        print(f"[DEBUG] 準備調用 open_notepad_tool")
                        result = self.system_tools.open_notepad_tool("")
                        print(f"[DEBUG] open_notepad_tool 返回結果: {result}")
                        return f"記事本應用程式已成功開啟,您可以開始輸入文字了。實際結果:{result}"
                    except Exception as e:
                        print(f"[DEBUG] 開啟記事本時發生錯誤: {e}")
                        return f"開啟記事本時發生錯誤: {e}"
                
                if "Action: 開啟空白Word" in error_msg:
                    print(f"[DEBUG] 檢測到空白Word開啟請求,直接執行真正的工具")
                    try:
                        print(f"[DEBUG] 準備調用 open_blank_word_tool")
                        result = self.system_tools.open_blank_word_tool("")
                        print(f"[DEBUG] open_blank_word_tool 返回結果: {result}")
                        return f"Word應用程式已成功開啟,您可以開始編輯文件了。實際結果:{result}"
                    except Exception as e:
                        print(f"[DEBUG] 開啟空白Word時發生錯誤: {e}")
                        return f"開啟空白Word時發生錯誤: {e}"
                
                if ("Action: 開啟Word並輸入內容" in error_msg or "Action: 開啟Word" in error_msg):
                    print(f"[DEBUG] 檢測到Word開啟請求,直接執行真正的工具")
                    try:
                        print(f"[DEBUG] 準備調用 open_word_tool")
                        result = self.system_tools.open_word_tool("")
                        print(f"[DEBUG] open_word_tool 返回結果: {result}")
                        return f"Word應用程式已成功開啟,您可以開始編輯文件了。實際結果:{result}"
                    except Exception as e:
                        print(f"[DEBUG] 開啟Word時發生錯誤: {e}")
                        return f"開啟Word時發生錯誤: {e}"
                
                # 處理自然語言請求(沒有標準Action格式的情況)
                if (("我想畫畫" in error_msg or "開小畫家" in error_msg or "開啟小畫家" in error_msg or "打開小畫家" in error_msg) and 
                    "Action:" not in error_msg):
                    print(f"[DEBUG] 檢測到自然語言小畫家請求")
                    try:
                        result = self.system_tools.open_paint_tool("")
                        return f"小畫家應用程式已成功開啟,您可以開始繪圖了。實際結果:{result}"
                    except Exception as e:
                        return f"開啟小畫家時發生錯誤: {e}"
                
                # 處理自然語言Word請求 - 智能判斷是否需要寫入內容
                if (("開啟word" in error_msg.lower() or "開word" in error_msg or "打開word" in error_msg.lower() or
                     "開啟Word" in error_msg or "開Word" in error_msg or "打開Word" in error_msg) and 
                     "Action:" not in error_msg):
                    print(f"[DEBUG] 檢測到自然語言Word請求")
                    
                    # 檢查是否包含寫入意圖的關鍵字
                    write_keywords = ["寫入", "輸入", "寫", "打字", "內容", "文字", "文件", "寫到", "放進", "加入"]
                    has_write_intent = any(keyword in error_msg for keyword in write_keywords)
                    
                    try:
                        if has_write_intent:
                            print(f"[DEBUG] 檢測到寫入意圖,使用 open_word_tool")
                            result = self.system_tools.open_word_tool("")
                            return f"Word應用程式已成功開啟並準備寫入內容。實際結果:{result}"
                        else:
                            print(f"[DEBUG] 純開啟請求,使用 open_blank_word_tool")
                            result = self.system_tools.open_blank_word_tool("")
                            return f"Word應用程式已成功開啟,您可以開始編輯文件了。實際結果:{result}"
                    except Exception as e:
                        return f"開啟Word時發生錯誤: {e}"
                
                # 檢查錯誤消息中是否包含實際的執行結果(這是針對已經執行過的情況)
                # 很多時候Agent實際執行了操作,只是輸出格式不正確
                elif ("Word已開啟" in error_msg or "Word已儲存" in error_msg or "Word檔案已儲存" in error_msg or
                    "小畫家已開啟" in error_msg or "記事本已開啟" in error_msg or
                    "Word 已開啟" in error_msg):  # 也檢查有空格的版本
                    # 直接返回成功消息,因為操作實際上已經成功了
                    if "Word已開啟" in error_msg or "Word 已開啟" in error_msg:
                        return "Word應用程式已成功開啟。"
                    elif "Word已儲存" in error_msg or "Word檔案已儲存" in error_msg:
                        return "Word檔案已成功儲存。"
                    elif "小畫家已開啟" in error_msg:
                        return "小畫家應用程式已成功開啟。"
                    elif "記事本已開啟" in error_msg:
                        return "記事本應用程式已成功開啟。"
                
                # 檢查是否是正常的Tool執行但輸出格式錯誤
                # 如果錯誤中包含 Action: 將已生成內容寫入Word,實際調用工具
                if "Action: 將已生成內容寫入Word" in error_msg:
                    print(f"[DEBUG] 檢測到正常的 write_generated_to_word_tool 調用,但輸出格式錯誤,實際執行工具")
                    try:
                        result = self.system_tools.write_generated_to_word_tool("")
                        return result
                    except Exception as e:
                        print(f"[DEBUG] 執行 write_generated_to_word_tool 時發生錯誤: {e}")
                        return f"寫入Word時發生錯誤: {e}"
                
                # 檢查是否是儲存Word工具的正常調用
                if "Action: 儲存Word文件" in error_msg:
                    print(f"[DEBUG] 檢測到正常的 save_word_tool 調用,但輸出格式錯誤,實際執行工具")
                    try:
                        # 提取Action Input參數
                        filename = ""
                        if "Action Input:" in error_msg:
                            input_part = error_msg.split("Action Input:")[1].split("Observation:")[0].strip()
                            filename = input_part.strip('"\' ')
                        
                        if not filename:
                            filename = "我的小說"  # 默認檔名
                        
                        print(f"[DEBUG] 實際調用 save_word_tool,檔名: '{filename}'")
                        result = self.system_tools.save_word_tool(filename)
                        return result
                    except Exception as e:
                        print(f"[DEBUG] 執行 save_word_tool 時發生錯誤: {e}")
                        return f"儲存Word檔案時發生錯誤: {e}"
                
                # 檢查是否是其他Word工具的正常調用
                if ("Action: 開啟Word" in error_msg):
                    print(f"[DEBUG] 檢測到正常的工具調用,但輸出格式錯誤")
                    # 提取Observation部分作為結果
                    if "Observation:" in error_msg:
                        obs_part = error_msg.split("Observation:")[1].split("Thought:")[0].strip()
                        return obs_part if obs_part else "操作已完成。"
                    return "操作已完成。"
                
                # 檢查是否是內容生成工具調用
                if "Action: 內容生成工具" in error_msg:
                    print(f"[DEBUG] 檢測到正常的 generate_content_tool 調用,但輸出格式錯誤,實際執行工具")
                    try:
                        # 提取Action Input參數
                        topic = ""
                        if "Action Input:" in error_msg:
                            input_part = error_msg.split("Action Input:")[1].split("Observation:")[0].strip()
                            topic = input_part.strip('"\' ')
                        
                        if not topic:
                            topic = "小說"  # 默認主題
                        
                        print(f"[DEBUG] 實際調用 generate_content_tool,主題: '{topic}'")
                        result = self.system_tools.generate_content_tool(topic)
                        return result
                    except Exception as e:
                        print(f"[DEBUG] 執行 generate_content_tool 時發生錯誤: {e}")
                        return f"生成內容時發生錯誤: {e}"
                
                # 嘗試從錯誤信息中提取動作 - 處理各種Word開啟請求(包括簡單的"開啟"命令)
                if (("開啟Word並輸入內容" in error_msg or "輸入Word" in error_msg or "寫進Word" in error_msg or 
                     "開啟Word" in error_msg or "打開Word" in error_msg or "open word" in error_msg.lower() or 
                     "開啟word" in error_msg or "打開word" in error_msg) and
                    "將已生成內容寫入Word" not in error_msg and "寫內容到Word" not in error_msg):
                    print(f"[DEBUG] 檢測到Word開啟請求,直接調用工具")
                    
                    # 簡化的防重複執行機制 - 只檢查一個時間戳
                    import time
                    current_time = time.time()
                    if hasattr(self.system_tools, '_last_word_operation_time'):
                        time_diff = current_time - self.system_tools._last_word_operation_time
                        if time_diff < 2:  # 縮短到2秒避免阻擋正常請求
                            print(f"[DEBUG] Word操作在{time_diff:.1f}秒前剛執行過,避免重複調用")
                            return "Word操作已完成,內容已寫入。"
                    
                    # 記錄操作時間
                    self.system_tools._last_word_operation_time = current_time
                    
                    try:
                        # 提取Action Input (如果有的話)
                        content = ""
                        if "Action Input:" in error_msg:
                            input_part = error_msg.split("Action Input:")[1].split("Observation:")[0].strip()
                            content = input_part.strip('"\' ')
                        
                        # 如果沒有內容或內容為空,或者是一般性的說明文字,嘗試使用最近的分析結果
                        if (not content.strip() or 
                            "沒有預設" in content or 
                            "請提供" in content or 
                            "我目前沒有" in content or
                            len(content.strip()) < 50):  # 如果內容太短,可能是預設回應
                            if (hasattr(self.app_instance, 'last_analysis_result') and 
                                self.app_instance.last_analysis_result.strip()):
                                content = self.app_instance.last_analysis_result
                                print(f"[DEBUG] 在錯誤處理中使用保存的分析結果,長度: {len(content)}")
                        
                        print(f"[DEBUG] 準備調用 _actually_open_word,內容長度: {len(content)}")
                        # 直接調用我們的內部工具
                        result = self.system_tools._actually_open_word(content)
                        print(f"[DEBUG] _actually_open_word 返回結果: {result}")
                        # 返回最終答案格式,讓Agent知道任務完成
                        return f"Word已開啟成功。{result}"
                    except Exception as e:
                        print(f"[DEBUG] 執行Word開啟時發生錯誤: {e}")
                        return f"Word已開啟失敗: {e}"
                
                elif ("寫入word" in error_msg.lower() or "寫入Word" in error_msg) and not any(x in error_msg for x in ["已將", "Word剛開啟", "內容已經寫入", "Word操作", "Word剛開啟過", "已執行內容寫入操作", "您希望我將其寫入Word嗎", "是否要寫入Word", "要寫入Word嗎", "寫入Word嗎", "將其寫入Word", "已生成", "生成完成", "Final Answer", "Thought:"]):
                    print(f"[DEBUG] 檢測到真正的寫入Word請求,智能判斷內容來源")
                    try:
                        # 添加防重複調用機制
                        import time
                        current_time = time.time()
                        if hasattr(self, '_last_word_open_time'):
                            time_diff = current_time - self._last_word_open_time
                            if time_diff < 5:  # 5秒內不重複開啟
                                print(f"[DEBUG] Word在{time_diff:.1f}秒前剛開啟過,避免重複調用")
                                return "Word剛開啟過,內容已經寫入完成。"
                        
                        # 檢查是否有現有內容
                        has_existing_content = False
                        content_source = ""
                        
                        # 檢查是否有分析結果
                        if (hasattr(self, 'last_analysis_result') and 
                            self.last_analysis_result and 
                            self.last_analysis_result.strip()):
                            has_existing_content = True
                            content_source = "分析結果"
                            print(f"[DEBUG] 找到分析結果,長度: {len(self.last_analysis_result)}")
                        
                        # 檢查是否有生成內容
                        elif (hasattr(self, 'last_generated_content') and 
                              self.last_generated_content and 
                              self.last_generated_content.strip()):
                            has_existing_content = True
                            content_source = "生成內容"
                            print(f"[DEBUG] 找到生成內容,長度: {len(self.last_generated_content)}")
                        
                        # 檢查是否有上傳檔案內容
                        elif (hasattr(self, 'uploaded_file_content') and 
                              self.uploaded_file_content and 
                              self.uploaded_file_content.strip()):
                            has_existing_content = True
                            content_source = "上傳檔案內容"
                            print(f"[DEBUG] 找到上傳檔案內容,長度: {len(self.uploaded_file_content)}")
                        
                        if has_existing_content:
                            print(f"[DEBUG] 檢測到現有{content_source},使用write_generated_to_word_tool")
                            result = self.system_tools.write_generated_to_word_tool("")
                            return f"已將{content_source}寫入Word。{result}"
                        else:
                            print(f"[DEBUG] 沒有現有內容,使用write_to_word_tool生成新內容")
                            # 提取主題
                            topic = ""
                            if "Action Input:" in error_msg:
                                input_part = error_msg.split("Action Input:")[1].split("Observation:")[0].strip()
                                topic = input_part.strip('"\' ')
                            
                            result = self.system_tools.write_to_word_tool(topic)
                            return f"已執行內容寫入操作: {result}"
                            
                    except Exception as e:
                        return f"執行內容寫入時發生錯誤: {e}"
                
                elif "儲存Word文件" in error_msg:
                    print(f"[DEBUG] 檢測到儲存Word請求,直接調用工具")
                    try:
                        # 提取檔案名稱
                        filename = ""
                        if "Action Input:" in error_msg:
                            input_part = error_msg.split("Action Input:")[1].split("Observation:")[0].strip()
                            input_part = input_part.strip('"\' ')
                            
                            # 嘗試解析JSON格式
                            try:
                                import json
                                input_data = json.loads(input_part)
                                if isinstance(input_data, dict) and "filename" in input_data:
                                    filename = input_data["filename"]
                                else:
                                    filename = input_part
                            except (json.JSONDecodeError, ValueError):
                                # 如果不是JSON格式,直接使用原始內容
                                filename = input_part
                        
                        print(f"[DEBUG] 提取到的檔名: '{filename}'")
                        
                        # 檢查檔名是否有效
                        if not filename.strip():
                            print(f"[DEBUG] 沒有提供檔名,詢問用戶")
                            return "請問要將檔案儲存為什麼名稱?"
                        
                        # 檢查是否是一般性名稱
                        generic_names = ["文件", "檔案", "word文件", "word檔案", "內容", "文字"]
                        if filename.strip().lower() in generic_names:
                            print(f"[DEBUG] 檔名是一般性名稱,詢問用戶")
                            return "請問要將檔案儲存為什麼名稱?"
                        
                        print(f"[DEBUG] 準備儲存Word檔案,檔名: '{filename}'")
                        result = self.system_tools.save_word_tool(filename)
                        print(f"[DEBUG] 儲存Word返回結果: {result}")
                        return f"Word檔案已儲存。{result}"
                    except Exception as e:
                        print(f"[DEBUG] 執行Word儲存時發生錯誤: {e}")
                        return f"Word檔案儲存失敗: {e}"
                
                elif "檔案內容分析" in error_msg or "檔案分析" in error_msg:
                    print(f"[DEBUG] 檢測到檔案分析請求,直接調用工具")
                    try:
                        # 提取分析類型
                        analysis_type = "詳細分析"
                        if "分析類型" in error_msg:
                            # 嘗試提取分析類型
                    

上一篇
DAY 28
下一篇
DAY 30
系列文
我的 AI 助手開發30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言