20 KiB
20 KiB
專案架構及開發文檔
專案概述
Wolf Chat 是一個基於 MCP (Modular Capability Provider) 框架的聊天機器人助手,專為與遊戲 "Last War-Survival Game" 整合而設計。該機器人:
- 使用螢幕辨識技術監控遊戲聊天視窗
- 偵測包含 "wolf" 或 "Wolf" 關鍵字的聊天訊息
- 通過 LLM (語言模型) 生成回應
- 使用 UI 自動化技術將回應輸入到遊戲聊天介面
專案以英文編寫程式碼,但主要輸出和日誌以繁體中文顯示,方便使用者理解。
系統架構
核心元件
-
主控模塊 (main.py)
- 協調各模塊的工作
- 初始化 MCP 連接
- 設置並管理主要事件循環
- 處理程式生命週期管理和資源清理
-
LLM 交互模塊 (llm_interaction.py)
- 與語言模型 API 通信
- 管理系統提示與角色設定
- 處理語言模型的工具調用功能
- 格式化 LLM 回應
- 提供工具結果合成機制
-
UI 互動模塊 (ui_interaction.py)
- 使用圖像辨識技術監控遊戲聊天視窗
- 檢測聊天泡泡與關鍵字
- 複製聊天內容和獲取發送者姓名
- 將生成的回應輸入到遊戲中
-
MCP 客戶端模塊 (mcp_client.py)
- 管理與 MCP 服務器的通信
- 列出和調用可用工具
- 處理工具調用的結果和錯誤
-
配置模塊 (config.py)
- 集中管理系統參數和設定
- 整合環境變數
- 配置 API 密鑰和服務器設定
-
角色定義 (persona.json)
- 詳細定義機器人的人格特徵
- 包含外觀、說話風格、個性特點等資訊
- 提供給 LLM 以確保角色扮演一致性
-
視窗設定工具 (window-setup-script.py)
- 輔助工具,用於設置遊戲視窗的位置和大小
- 方便開發階段截取 UI 元素樣本
資料流程
[遊戲聊天視窗]
↑↓
[UI 互動模塊] <→ [圖像樣本庫]
↓
[主控模塊] ← [角色定義]
↑↓
[LLM 交互模塊] <→ [語言模型 API]
↑↓
[MCP 客戶端] <→ [MCP 服務器]
技術實現
核心功能實現
聊天監控與觸發機制
系統使用基於圖像辨識的方法監控遊戲聊天界面:
- 泡泡檢測(含 Y 軸優先配對):通過辨識聊天泡泡的左上角 (TL) 和右下角 (BR) 角落圖案定位聊天訊息。
- 多外觀支援:為了適應玩家可能使用的不同聊天泡泡外觀 (skin),一般用戶泡泡的偵測機制已被擴充,可以同時尋找多組不同的角落模板 (例如
corner_tl_type2.png,corner_br_type2.png等)。機器人泡泡目前僅偵測預設的角落模板。 - 配對邏輯優化:在配對 TL 和 BR 角落時,系統現在會優先選擇與 TL 角落 Y 座標最接近 的有效 BR 角落,以更好地區分垂直堆疊的聊天泡泡。
- 多外觀支援:為了適應玩家可能使用的不同聊天泡泡外觀 (skin),一般用戶泡泡的偵測機制已被擴充,可以同時尋找多組不同的角落模板 (例如
- 關鍵字檢測:在泡泡區域內搜尋 "wolf" 或 "Wolf" 關鍵字圖像。
- 內容獲取:點擊關鍵字位置,使用剪貼板複製聊天內容。
- 發送者識別(含氣泡重新定位與偏移量調整):關鍵步驟 - 為了提高在動態聊天環境下的穩定性,系統在獲取發送者名稱前,會執行以下步驟:
a. 初始偵測:像之前一樣,根據偵測到的關鍵字定位觸發的聊天泡泡。
b. 氣泡快照:擷取該聊天泡泡的圖像快照。
c. 重新定位:在點擊頭像前,使用該快照在當前聊天視窗區域內重新搜尋氣泡的最新位置。
d. 計算座標(新偏移量):
- 如果成功重新定位氣泡,則根據找到的新左上角座標 (
new_tl_x,new_tl_y),應用新的偏移量計算頭像點擊位置:x = new_tl_x - 45(AVATAR_OFFSET_X_REPLY),y = new_tl_y + 10(AVATAR_OFFSET_Y_REPLY)。 - 如果無法重新定位(例如氣泡已滾動出畫面),則跳過此次互動,以避免點擊錯誤位置。 e. 互動(含重試): - 使用計算出的(新的)頭像位置進行第一次點擊。 - 檢查是否成功進入個人資料頁面 (Profile_page.png)。 - 如果失敗:系統會使用步驟 (b) 的氣泡快照,在聊天區域內重新定位氣泡,重新計算頭像座標,然後再次嘗試點擊。此過程最多重複 3 次。 - 如果成功(無論是首次嘗試還是重試成功):繼續導航菜單,最終複製用戶名稱。 - 如果重試後仍失敗:放棄獲取該用戶名稱。 f. 原始偏移量:原始的-55像素水平偏移量 (AVATAR_OFFSET_X) 仍保留在程式碼中,用於其他不需要重新定位或不同互動邏輯的場景(例如remove_user_position功能)。 - 防重複處理:使用位置比較和內容歷史記錄防止重複回應。
LLM 整合
系統使用基於 OpenAI API 的介面與語言模型通信:
- 模型選擇:目前使用
anthropic/claude-3.7-sonnet模型 (改進版) - 系統提示:精心設計的提示確保角色扮演和功能操作
- 工具調用:支持模型使用 web_search 等工具獲取資訊
- 工具處理循環:實現了完整的工具調用、結果處理和續發邏輯
- 結果合成:添加了從工具調用結果合成回應的機制 (新增功能)
多服務器連接
系統可以同時連接多個 MCP 服務器:
- 並行初始化:使用 asyncio 並行連接配置的所有服務器
- 工具整合:自動發現並整合各服務器提供的工具
- 錯誤處理:處理連接失敗和工具調用異常
異步架構
系統使用 Python 的 asyncio 作為核心異步框架:
- 主事件循環:處理 MCP 連接、LLM 請求和 UI 監控
- 線程安全通信:UI 監控在獨立線程中運行,通過線程安全隊列與主循環通信
- 資源管理:使用 AsyncExitStack 管理異步資源的生命週期
- 清理機制:實現了優雅的關閉和清理流程
UI 自動化
系統使用多種技術實現 UI 自動化:
- 圖像辨識:使用 OpenCV 和 pyautogui 進行圖像匹配和識別。
- 鍵鼠控制:模擬鼠標點擊和鍵盤操作。
- 剪貼板操作:使用 pyperclip 讀寫剪貼板。
- 狀態式處理:基於 UI 狀態判斷的互動流程,確保操作穩定性。
- 針對性回覆(上下文激活):
- 時機:在成功獲取發送者名稱並返回聊天介面後,但在將觸發資訊放入隊列傳遞給主線程之前。
- 流程:
a. 再次使用氣泡快照重新定位觸發訊息的氣泡。
b. 如果定位成功,點擊氣泡中心,並等待 0.25 秒(增加的延遲時間)以允許 UI 反應。
c. 尋找並點擊彈出的「回覆」按鈕 (
reply_button.png)。 d. 如果成功點擊回覆按鈕,則設置一個reply_context_activated標記為True。 e. 如果重新定位氣泡失敗或未找到回覆按鈕,則該標記為False。 - 傳遞:將
reply_context_activated標記連同其他觸發資訊(發送者、內容、氣泡區域)一起放入隊列。 - 發送:主控模塊 (
main.py) 在處理send_reply命令時,不再需要執行點擊回覆的操作,只需直接調用send_chat_message即可(因為如果reply_context_activated為True,輸入框應已準備好)。
配置與部署
依賴項
主要依賴項目包括:
- openai: 與語言模型通信
- mcp: MCP 框架核心
- pyautogui, opencv-python: 圖像辨識與自動化
- pyperclip: 剪貼板操作
- pygetwindow: 窗口控制
- python-dotenv: 環境變數管理
環境設定
- API 設定:通過 .env 文件或環境變數設置 API 密鑰
- MCP 服務器配置:在 config.py 中配置要連接的 MCP 服務器
- UI 樣本:需要提供特定遊戲界面元素的截圖模板
- 視窗位置:可使用 window-setup-script.py 調整遊戲視窗位置
最近改進(2025-04-17)
工具調用與結果處理優化
針對使用工具時遇到的回應問題,我們進行了以下改進:
-
模型切換:
- 已取消
-
系統提示強化:
- 重寫系統提示,將角色人格與工具使用指南更緊密結合
- 添加明確指示,要求 LLM 在工具調用後提供非空回應
- 添加好與壞的示例,使模型更好地理解如何以角色方式融合工具信息
-
工具結果處理機制:
- 實現了工具結果追蹤系統,保存所有工具調用結果
- 添加了對非空回應的追蹤,確保能在多次循環間保持連續性
- 開發了合成回應生成器,能從工具結果創建符合角色的回應
-
回應解析改進:
- 重寫
parse_structured_response函數,處理更多回應格式 - 添加回應有效性檢測,確保只有有效回應才發送到遊戲
- 強化 JSON 解析能力,更好地處理不完整或格式不標準的回應
- 重寫
-
主程序流程優化:
- 修改了主流程中的回應處理邏輯,增加回應有效性檢查
- 改進了工具調用循環處理,確保完整收集結果
- 添加了更詳細的日誌記錄,方便排查問題
這些優化確保了即使在複雜工具調用後,Wolfhart 也能保持角色一致性,並提供合適的回應。無效回應不再發送到遊戲,提高了用戶體驗。
最近改進(2025-04-18)
支援多種一般聊天泡泡外觀,並修正先前錯誤配置
- UI 互動模塊 (
ui_interaction.py):- 修正:先前錯誤地將多外觀支援應用於機器人泡泡。現已修正
find_dialogue_bubbles函數,使其能夠載入並搜尋多組一般用戶泡泡的角落模板(例如corner_tl_type2.png,corner_br_type2.png等)。 - 允許任何類型的一般用戶左上角與任何類型的一般用戶右下角進行配對,只要符合幾何條件。
- 機器人泡泡的偵測恢復為僅使用預設的
bot_corner_tl.png和bot_corner_br.png模板。 - 這提高了對使用了自訂聊天泡泡外觀的一般玩家訊息的偵測能力。
- 修正:先前錯誤地將多外觀支援應用於機器人泡泡。現已修正
- 模板文件:
- 在
ui_interaction.py中為一般角落定義了新類型模板的路徑(_type2,_type3)。 - 注意: 需要在
templates資料夾中實際添加對應的corner_tl_type2.png,corner_br_type2.png等圖片檔案才能生效。
- 在
- 文件更新 (
ClaudeCode.md):- 在「技術實現」部分更新了泡泡檢測的說明。
- 添加了此「最近改進」條目,並修正了先前的描述。
頭像點擊偏移量調整
- UI 互動模塊 (
ui_interaction.py):- 將
AVATAR_OFFSET_X常數的值從-50調整為-55。 - 這統一了常規關鍵字觸發流程和
remove_user_position功能中計算頭像點擊位置時使用的水平偏移量。
- 將
- 文件更新 (
ClaudeCode.md):- 在「技術實現」的「發送者識別」部分強調了點擊位置是相對於觸發泡泡計算的,並註明了新的偏移量。
- 添加了此「最近改進」條目。
聊天泡泡重新定位以提高穩定性
- UI 互動模塊 (
ui_interaction.py):- 在
run_ui_monitoring_loop中,於偵測到關鍵字並成功複製文字後、獲取發送者名稱前,加入了新的邏輯:- 擷取觸發氣泡的圖像快照。
- 使用
pyautogui.locateOnScreen在聊天區域內重新尋找該快照的當前位置。 - 若找到,則根據新位置的左上角座標和新的偏移量 (
AVATAR_OFFSET_X_RELOCATED = -50) 計算頭像點擊位置。 - 若找不到,則記錄警告並跳過此次互動。
- 新增了
AVATAR_OFFSET_X_RELOCATED和BUBBLE_RELOCATE_CONFIDENCE常數。
- 在
- 目的:解決聊天視窗內容滾動後,原始偵測到的氣泡位置失效,導致點擊錯誤頭像的問題。透過重新定位,確保點擊的是與觸發訊息相對應的頭像。
- 文件更新 (
ClaudeCode.md):- 更新了「技術實現」中的「發送者識別」部分,詳細說明了重新定位的步驟。
- 在此「最近改進」部分添加了這個新條目。
互動流程優化 (頭像偏移、氣泡配對、針對性回覆)
- UI 互動模塊 (
ui_interaction.py):- 頭像偏移量調整:修改了重新定位氣泡後計算頭像座標的邏輯,使用新的偏移量:左
-45(AVATAR_OFFSET_X_REPLY),下+10(AVATAR_OFFSET_Y_REPLY)。原始的-55偏移量 (AVATAR_OFFSET_X) 保留用於其他功能。 - 氣泡配對優化:修改
find_dialogue_bubbles函數,使其在配對左上角 (TL) 和右下角 (BR) 時,優先選擇 Y 座標差異最小的 BR 角落,以提高垂直相鄰氣泡的區分度。 - 頭像點擊重試:修改
retrieve_sender_name_interaction函數,增加了最多 3 次的重試邏輯。如果在點擊頭像後未能檢測到個人資料頁面,會嘗試重新定位氣泡並再次點擊。 - 針對性回覆時機調整與延遲增加:
- 將點擊氣泡中心和回覆按鈕的操作移至成功獲取發送者名稱並返回聊天室之後、將觸發資訊放入隊列之前。
- 增加了點擊氣泡中心後、尋找回覆按鈕前的等待時間至 0.25 秒,以提高在 UI 反應較慢時找到按鈕的成功率。
- 在放入隊列的數據中增加
reply_context_activated標記,指示是否成功激活了回覆上下文。 - 簡化了處理
send_reply命令的邏輯,使其僅負責發送消息。
- 氣泡快照保存 (用於除錯):在偵測到關鍵字後,擷取用於重新定位的氣泡圖像快照 (
bubble_snapshot) 時,會將此快照保存到debug_screenshots文件夾中,檔名格式為debug_relocation_snapshot_X.png(X 為 1 到 5 的循環數字)。這取代了先前僅保存氣泡區域截圖的邏輯。
- 頭像偏移量調整:修改了重新定位氣泡後計算頭像座標的邏輯,使用新的偏移量:左
- 目的:
- 進一步提高獲取發送者名稱的穩定性。
- 改善氣泡配對的準確性。
- 調整針對性回覆的流程,使其更符合邏輯順序,並通過增加延遲提高可靠性。
- 提供用於重新定位的實際圖像快照,方便除錯。
- 文件更新 (
ClaudeCode.md):- 更新了「技術實現」中的「泡泡檢測」、「發送者識別」部分。
- 更新了「UI 自動化」部分關於「針對性回覆」的說明,反映了新的時機、標記和增加的延遲。
- 在此「最近改進」部分更新了這個匯總條目,以包含最新的修改(包括快照保存和延遲增加)。
UI 監控暫停與恢復機制 (2025-04-18)
- 目的:解決在等待 LLM 回應期間,持續的 UI 監控可能導致的不穩定性或干擾問題,特別是與
remove_position等需要精確 UI 狀態的操作相關。 ui_interaction.py:- 引入了全局(模塊級)
monitoring_paused_flag列表(包含一個布爾值)。 - 在
run_ui_monitoring_loop的主循環開始處檢查此標誌。若為True,則循環僅檢查命令隊列中的resume命令並休眠,跳過所有 UI 偵測和觸發邏輯。 - 在命令處理邏輯中添加了對
pause和resume動作的處理,分別設置monitoring_paused_flag[0]為True或False。
- 引入了全局(模塊級)
ui_interaction.py(進一步修改):- 修正命令處理邏輯:修改了
run_ui_monitoring_loop的主循環。現在,在每次迭代開始時,它會使用一個內部while True循環和command_queue.get_nowait()來處理完隊列中所有待處理的命令(包括pause,resume,send_reply,remove_position等)。 - 狀態檢查後置:只有在清空當前所有命令後,循環才會檢查
monitoring_paused_flag的狀態。如果標誌為True,則休眠並跳過 UI 監控部分;如果為False,則繼續執行 UI 監控(畫面檢查、氣泡偵測等)。 - 目的:解決先前版本中
resume命令可能導致 UI 線程過早退出暫停狀態,從而錯過緊隨其後的send_reply或remove_position命令的問題。確保所有來自main.py的命令都被及時處理。
- 修正命令處理邏輯:修改了
main.py:- (先前修改保持不變)在主處理循環 (
run_main_with_exit_stack的while True循環) 中:- 在從
trigger_queue獲取數據後、調用llm_interaction.get_llm_response之前,向command_queue發送{ 'action': 'pause' }命令。 - 使用
try...finally結構,確保在處理 LLM 回應(包括命令處理和發送回覆)之後,向command_queue發送{ 'action': 'resume' }命令,無論處理過程中是否發生錯誤。
- 在從
- (先前修改保持不變)在主處理循環 (
remove_position 穩定性改進 (使用快照重新定位) (2025-04-19)
- 目的:解決
remove_position命令因聊天視窗滾動導致基於舊氣泡位置計算座標而出錯的問題。 ui_interaction.py(run_ui_monitoring_loop):- 在觸發事件放入
trigger_queue的數據中,額外添加了bubble_snapshot(觸發氣泡的圖像快照)和search_area(用於快照的搜索區域)。
- 在觸發事件放入
main.py:- 修改了處理
remove_position命令的邏輯,使其從trigger_data中提取bubble_snapshot和search_area,並將它們包含在發送給command_queue的命令數據中。
- 修改了處理
ui_interaction.py(remove_user_position函數):- 修改了函數簽名,以接收
bubble_snapshot和search_area參數。 - 在函數執行開始時,使用傳入的
bubble_snapshot和search_area調用pyautogui.locateOnScreen來重新定位觸發氣泡的當前位置。 - 如果重新定位失敗,則記錄錯誤並返回
False。 - 如果重新定位成功,則後續所有基於氣泡位置的計算(包括尋找職位圖標的搜索區域
search_region和點擊頭像的座標avatar_click_x,avatar_click_y)都將使用這個新找到的氣泡座標。
- 修改了函數簽名,以接收
- 效果:確保
remove_position操作基於氣泡的最新位置執行,提高了在動態滾動的聊天界面中的可靠性。
開發建議
優化方向
-
UI 辨識強化:
- 改進泡泡匹配算法,提高可靠性
- 添加文字 OCR 功能,減少依賴剪貼板
- 擴展關鍵字檢測能力
-
LLM 進一步優化:
- 繼續微調系統提示,平衡角色扮演與工具使用
- 研究可能的上下文壓縮技術,處理長對話歷史
- 為更多查詢類型添加專門的結果處理邏輯
-
系統穩定性:
- 擴展錯誤處理和復原機制
- 添加自動重啟和診斷功能
- 實現更多遙測和監控功能
-
對話能力增強:
- 實現對話歷史記錄
- 添加主題識別與記憶功能
- 探索多輪對話中的上下文理解能力
注意事項
- 圖像模板:確保所有必要的 UI 元素模板都已截圖並放置在 templates 目錄
- API 密鑰:保護 API 密鑰安全,不要將其提交到版本控制系統
- 窗口位置:UI 自動化對窗口位置和大小敏感,保持一致性
- LLM 模型選擇:在更改模型前測試其在工具調用方面的表現
分析與反思
架構優勢
- 模塊化設計:各功能區域職責明確,易於維護和擴展
- 基於能力的分離:MCP 框架提供良好的工具擴展性
- 非侵入式整合:不需要修改遊戲本身,通過 UI 自動化實現整合
- 錯誤處理分層:在多個層次實現錯誤處理,提高系統穩定性
潛在改進
- 更穩健的 UI 互動:當前的圖像辨識方法可能受游戲界面變化影響
- 擴展觸發機制:增加更多觸發條件,不僅限於關鍵字
- 對話記憶:實現對話歷史記錄,使機器人可以參考之前的互動
- 多語言支持:增強對不同語言的處理能力
- 模型適應性:開發更通用的提示和處理機制,適應不同的LLM模型
使用指南
啟動流程
- 確保遊戲已啟動且聊天介面可見
- 配置必要的 API 密鑰和服務器連接
- 運行
python main.py啟動系統 - 系統將自動監控聊天,偵測關鍵字並回應
日常維護
- 定期檢查 API 密鑰有效性
- 確保模板圖像與當前遊戲界面匹配
- 監控日誌以檢測可能的問題
- 定期檢查和備份 llm_debug.log 文件
故障排除
常見問題及解決方案:
- 無法識別泡泡: 更新模板圖像,調整 CONFIDENCE_THRESHOLD
- 複製內容失敗: 檢查點擊位置和遊戲界面一致性
- LLM 連接問題: 驗證 API 密鑰和網絡連接
- MCP 服務器連接失敗: 確認服務器配置正確並且運行中
- 工具調用後無回應: 檢查 llm_debug.log 文件,查看工具調用結果和解析過程