--- title: 04-Pro-Code Multi-Agent實戰演練 --- # Day3 - Pro-Code Multi-Agent 實戰演練 --- ## 一、前置需求 ### 1. 己完成本機開發環境準備 + Python環境 + Vistual Studio Code環境 + Azure CLI ### 2. Azure OpenAI Endpoint 建立 + dall-e-3模型現行只有這三個區域可用 `East US` `Australia East` 及`Sweden Central` + 需另外建立獨立 Azure OpenAI Endpoint + Azure Portal Search bar 輸入 `Azure OpenAI` ![image](https://hackmd.io/_uploads/BJtYYW4cgg.png) + Create ![image](https://hackmd.io/_uploads/ryCsKZV5ge.png) + Resource Group: 選擇Resrouce Group + Region: 建議選擇`Sweden Central` + Name: 輸入您的名稱 + Pricing Titer: Standard S0 + Next ![image](https://hackmd.io/_uploads/By2m5ZE9eg.png) + Network 及 Tags 都保持預設值,點選Next + Create ![image](https://hackmd.io/_uploads/HJeeoZVcee.png) + Go to resource ![image](https://hackmd.io/_uploads/rJc_jWEcxx.png) + Explore Azure AI Foundry portal ![image](https://hackmd.io/_uploads/BJZhoZVcgx.png) + Deployments ![image](https://hackmd.io/_uploads/HJCx2bNcle.png) + Deploy base model ![image](https://hackmd.io/_uploads/rkGE3W4qll.png) + Deploy `dall-e-3` model + Confirm ![image](https://hackmd.io/_uploads/HySYh-Nqxe.png) + Deploy ![image](https://hackmd.io/_uploads/HJQan-N5xe.png) ### 3、Azure Storge Account 建立 + 打開azure portal ![image](https://hackmd.io/_uploads/rJgUwVrzgg.png) + 搜尋Storage Accounts ![image](https://hackmd.io/_uploads/r1Xl2vtGll.png) + 建立Storage Account ![image](https://hackmd.io/_uploads/HJ5r2PFzee.png) + Region: 建議選擇 同一個Region ![image](https://hackmd.io/_uploads/HJrMjDYGgx.png) ![image](https://hackmd.io/_uploads/B1IDhPKGlx.png) + 建立Storage Account建立完成 ![image](https://hackmd.io/_uploads/BJrIlOFzle.png) + 新增Container ![image](https://hackmd.io/_uploads/HJi62wYGgx.png) + 新增Container - 名稱請輸入 "files" ![image](https://hackmd.io/_uploads/ryCk6PKzge.png) + 授予存取Storage Account 角色權限 - 左側選單 → 「Access Control (IAM)」 - Add role assignment ![image](https://hackmd.io/_uploads/HyT--sHilx.png) - 選擇「Storage Blob Data Contributor」角色 → 「Next」 ![image](https://hackmd.io/_uploads/B1SvZsriee.png) - Add role assignment - 選擇「User, group, or service principal」 - + select member - 選擇 您的帳號 (或需要存取Storage的使用者帳號) - 點擊 select - 點擊 review+assign ![image](https://hackmd.io/_uploads/SkL7foSoeg.png) ### 4、申請 OpenCage Geocoding API Key + 登入 https://opencagedata.com/api 選取 **Sing up for your geocoding API key** 獲取 API Key ![image](https://hackmd.io/_uploads/Hk4w4CYzee.png) ### 5. Download Code & Create Python venv + 請下載[Sample Code](https://1drv.ms/u/c/8302862bf709a02b/EdUE-6ghqUhOoVbMq3-OaWkBxT5pTpJ6_HXddTCZVS3sfQ?e=hQGMro) + Create a Virtual Environment 1. 切換Sample Code資料夾 ```bash cd "您的專案資料夾路徑" ``` 建立python venv ```bash python -m venv .venv ``` 2. Activate venv ```bash # For Windows .\.venv\Scripts\activate ``` 3. Install Dependency** ```bash # For Windows pip install -r requirements.txt ``` ### 6. Env 資訊填寫 #### AI Project + AIPROJECT_ENDPOINT ![image](https://hackmd.io/_uploads/H1YTFGNqge.png) #### Azure OpenAI + AZURE_OPENAI_ENDPOINT + AZURE_OPENAI_API_KEY ![image](https://hackmd.io/_uploads/r1VO5MV5el.png) #### dalle + AZURE_DALLE_ENDPOINT + AZURE_DALLE_KEY ![image](https://hackmd.io/_uploads/HkN6nME9gx.png) #### Azure Blob Storage + BLOB_ACCOUNT_NAME ![image](https://hackmd.io/_uploads/By_jzsBsxx.png) #### GEOCODING + GEOCODING_API_KEY: 您申請的API Key #### broswer-automation + PLAYWRIGHT_RESOURCE_NAME ![image](https://hackmd.io/_uploads/r1eCTMV5el.png) #### bing-search + BING_RESOURCE_NAME ![image](https://hackmd.io/_uploads/BJJrAMNcxx.png) #### mcp_url Day2 建立的 Web App Service SSE endpoint + MCP_AIRBNB_URL + MCP_BAZI_URL #### Custom Remote MCP + MCP_SSE_URL: 保持空白 --- ### 7. Test Your Project Setting 手動執行`00_test\test-ai-agent.ipynb` 確認沒有錯誤訊息 請確認右上角的Kernel已切換至您建立的Virtual Environment ![image](https://hackmd.io/_uploads/BJ5RxXEqgg.png) --- ## 二、 🚀 Quick Start --- ### 1. 📁 專案檔案說明 - `.env` 儲存環境變數,例如 API 金鑰、執行環境參數等。 - `requirements.txt` 定義本專案所需的 Python 套件列表。 - `agent_config.py` 定義 AI Agent 的資料結構。 + **name**: Agent 名稱 + **description**: Agent 描述 + **instruction**: Agent 人設 + **user_functions**: 本地客製化Function + **sk_plugins**: Semnatic Kernal Plugin名稱 + **mcp_tools**: MCP Tool Name + **bing_search**: 是否啟用Bing Search + **browser_automation**: 是否啟用Browser Automation + **code_interpreter**: 是否啟用Code Interpreter ![image](https://hackmd.io/_uploads/SJgXqQV9xg.png) - `tools.py` 提供各類工具函式,供 AI Agent 呼叫以完成任務。 + **get_lat_long**: 取得指定地區的經緯度資訊 + **get_weather_forecast**: 根據經緯度查詢該地的天氣預報 + **dale**: 使用 DALL·E 進行圖像生成 + **upload_file_to_blob**: 將檔案上傳至 Azure Blob Storage - `storage_token.py` 透過 **User Delegation Key (UDK)** 生成 Azure Blob Storage 的 **User Delegation SAS URL**。 + **get_cached_user_delegation_key**: 從快取或 Azure Blob Service 取得 **User Delegation Key (UDK)** 控制 UDK 的存活時間(最長 7 天 ) + **generate_user_delegation_sas_url**: 產生指定 Blob 的 **User Delegation SAS URL** - `utils.py` 此模組包含兩個主要類別,分別處理 Azure Blob 儲存與 AI Agent 的基本操作邏輯。 + **AzureBlobManager**: 支援檔案上傳與 SAS URL 產生 + **AIServiceAgent**: 封裝 Azure AI Agent 的操作流程,支援自定義工具、Bing 搜尋、Code Interpreter、Browser Automation 等功能。 - `travel_configs.py` --- ### 1. `TaskPlanner` - 任務總規劃師 - **描述**:Master planner that divides the task into subtasks. - **角色定位**:團隊的總指揮官,負責將使用者需求拆解為子任務並分派給最適合的 Agent。 - **執行限制**: - ❌ 不得執行任何子任務。 - ✅ 每一步都必須指派給一位 Agent。 - ✅ 回應需整合與說明,不可直接轉發原始輸出。 - **格式規範**: - 任務分派格式:`[__AgentName__] {task}` - 任務完成格式:`[Finished] {final reply}` - **工具設定**: --- ### 2. `TravelPlanner` - 行程規劃助手 - **描述**:A helpful assistant that can plan trips. - **角色定位**:根據使用者需求,產生具體的旅遊行程建議。 - **任務重點**: - ✅ 行程中需標示每一天的實際日期。 - ✅ 每個景點需包含「城市內的區域或地段名稱」。 - **工具設定**: --- ### 3. `RouteMaster` - 動線優化專家 - **描述**:An assistant that improves travel plans using real-world geography and transit. - **角色定位**:針對既有行程提供交通與住宿動線的專業優化建議。 - **任務重點**: - ✅ 避免頻繁轉乘與跨公司跳線。 - ✅ 檢查飯店與行程地點的地理合理性。 - ✅ 提供具體修改建議(如替代景點、飯店名稱、交通路線)。 - ✅ 必須重新產生完整行程表。 - **工具設定**: --- ### 4. `HotelFinder` - 住宿推薦與黃曆顧問 - **描述**:Helps users find accommodations via Airbnb and provides Chinese calendar insights. - **角色定位**:根據行程與預算推薦住宿,並提供傳統農民曆的旅遊建議。 - **任務重點**: - ✅ 根據地點、預算與偏好推薦住宿。 - ✅ 提供住宿名稱、地址、聯絡方式與訂房連結。 - ✅ 查詢農民曆,提供是否適合旅遊的建議。 - **工具使用規則**: - 所有回應必須使用工具,禁止直接回答。 - 工具呼叫語言需使用英文,回應可翻譯。 - Airbnb 搜尋結果需使用 `id` 呼叫 `airbnb_listing_details` 取得詳細資訊。 - **工具設定**: - MCP 工具:✅ `mcp_airbnb_server`, `mcp_bazi_server` --- ### 5. `WeatherAdvisor` - 天氣顧問 - **描述**:An assistant that uses weather data to adjust travel plans. - **角色定位**:根據每日天氣預報,協助使用者調整行程安排。 - **任務重點**: - ✅ 使用 `get_weather_forecast` 查詢指定日期與地點(需為英文地名)的天氣。 - ✅ 若天氣不佳,建議改為室內景點;若天氣良好,推薦戶外活動。 - ✅ 建議內容需具體、合理,並配合原本動線。 - **工具設定**: - 使用函式:✅ `get_weather_forecast` --- ### 6. `TripBudget` - 預算規劃師 - **描述**:Evaluates real travel costs and fills in Microsoft Forms budget. - **角色定位**:根據完整行程進行成本分析、填寫預算表單並產出報告。 - **任務流程**: 1. ✅ 成本分析(使用 Bing 搜尋) 2. ✅ 表單填寫(使用瀏覽器自動化) 3. ✅ 預算報告產出 - **完成檢查**: - 回應需包含:「成本分析 ✔️、表單填寫 ✔️、預算報告 ✔️」 - 若有步驟未完成,必須補足。 - **工具設定**: - 瀏覽器自動化:✅ - Bing 搜尋:✅ --- ### 7. `TravelStoryHTMLnImage` - HTML 行程故事產生器 - **描述**:Formats a complete travel plan into styled HTML, embedding image and Google Maps. - **角色定位**:將完整行程轉換為 HTML 文件,包含地圖、天氣、圖片與排版。 - **任務重點**: - ✅ 每日需包含天氣、交通方式、飯店名稱(加粗)。 - ✅ 使用 `get_lat_long` 取得座標並嵌入 Google Maps iframe。 - ✅ 使用 `dalle` 產生一張代表整趟旅程的圖片並嵌入。 - ✅ 產出 HTML 檔案並提供 Markdown 下載連結。 - ✅ 回應結尾必須包含 `TERMINATE`。 - **PDF 支援**: - ✅ 若產出 PDF,需使用內建中文字型(如 STSong-Light)避免相容性問題。 - **工具設定**: - 使用函式:✅ `dalle`, `get_lat_long` - Code Interpreter:✅ --- ### 2. 🧠 single_agent 模組 此模組包含Single Agent的應用範例: 1. `01_Travel_Planner.ipynb` - [ ] 在**user_text**中輸入您的旅遊計劃,例如: ```shell 明天要從台北出發去東京,請規劃一個2天1夜從成田機場進, 羽田機場出的行程,以下是要點: 1. 每天晚上不同飯店入住,請提供名稱; 2. 依天氣安排行程; 3. 提供行前注意事項提醒; ``` - [ ] 請記住**thread id** `thread_xxxxxx`. ![image](https://hackmd.io/_uploads/rJqhrmVcgg.png) 2. `02_Weather_Advisor.ipynb` - [ ] 置換Travel Planer產生的Thread id ![image](https://hackmd.io/_uploads/SJYHw_TGxx.png) - [ ] 在**user_text**中輸入您的請求,例如: ```shell 請根據實際天氣狀況進行行程調整 ``` 3. `03_Route_Master.ipynb` - [ ] 置換Travel Planer產生的Thread id - [ ] 在**user_text**中輸入您的請求,例如: ```shell 請從你的觀點來檢視這份行程,若有不同區域頻繁來回移動的問題,也請提出建議與批評,並重新產生行程表 ``` 4. `04_Hotel_Finder.ipynb` - [ ] 置換Travel Planer產生的Thread id - [ ] 在**user_text**中輸入您的請求,例如: ```shell 請從你的觀點來依據使用者的需求找到目前可預定且預算為100~200美元的Hotel及農民曆的旅遊資訊,並更新行程表 ``` 5. `05_Trip_Budget.ipynb` - [ ] 置換Travel Planer產生的Thread id - [ ] 在**user_text**中輸入您的請求,例如: ```shell 根據完整的旅遊行程,分析所有預算項目,並依照今天最新匯率統一換算為台幣。請將預估的旅遊預算填寫至指定表單 ``` 6. `06_TravelStory_HTML_Image.ipynb` - [ ] 置換Travel Planer產生的Thread id - [ ] 在**user_text**中輸入您的請求,例如: ```shell 請參考各位專家的意見後, 將最終版本的行程產生為HTML檔案 ``` - [ ] Agent產生的HTML檔案儲存在Sandbox 例如:**sandbox:/mnt/data/travel_plan.html**,需將檔案拉出後儲存至Azure Storage Account (sas token於七天後失效) ![image](https://hackmd.io/_uploads/HkYSdQNcex.png) ```shell bot_reply1 = app.retrieve_message() ``` - [ ] 已將Sandbox檔案取出後載入Azure Blob Storage ![image](https://hackmd.io/_uploads/SyRhOX45ge.png) 7. `07_Task_Planner.ipynb` - [ ] 在**user_text**中輸入您的旅遊計劃,Planner Agent不執行任務只負責分派工作,例如: ```shell 明天要從台北出發去富國島請規劃八天七夜的行程: 1. 依天氣安排行程; 2. 提供行前注意事項提醒 3. 前三天住Vinpearl Wonderworld Phu Quoc, 接下來住二天 Premier Residences Phu Quoc Emerald Bay Managed by Accor, 最後二天住 InterContinental Phu Quoc Long Beach Resort by IHG ``` ![image](https://hackmd.io/_uploads/SJZRFXNqxl.png) ### 3. 🤖 multi-agent 模組 --- 1. A_orchestration_planner\ **01_orchestration_planner** - `team.py`: Orchestration Planner的主程式:`01_orchestrate_foundry_agents_planner.ipynb` + **模組說明**: 此模組定義了一個 `Team` 類別,用於協調一個由多個 AI Agent 組成的團隊,透過一個「Planner」與多個「Workers」的架構,實現多步驟的任務分工與協作。 + **參數說明**: - `planner_config`:負責任務規劃的 Agent 設定(繼承自 `AgentConfig`)。 - `worker_configs`:一組工作者 Agent 的設定清單。 - `max_steps`:最大執行步驟數,預設為 10。 + **流程說明**: 1. 將使用者的Input傳給Planner。 2. Planner回應後,若包含 `[__AgentName__]` 標記,則將任務交由對應Worker處理。 3. Workwer執行後回傳結果,並將結果回饋給Planner。 4. 若Planner回應以 `[Finished]` 開頭,則流程結束並回傳最終結果。 5. 若超過 `max_steps` 步驟仍未完成,則拋出例外。 + **邏輯說明**: 1. 所有Worker共用一個對話 thread(`shared_worker_thread_id`),以利上下文共享。 2. Planner使用獨立 thread,避免干擾。 3. 支援自定義工具(如 MCP、Bing、Code Interpreter、Browser Automation)。 4. 每次Worker回應後,若有生成檔案會自動上傳至Azure Blob Storage並將結果回傳給Planner。 --- - `01_orchestrate_foundry_agents_planner.ipynb` - [ ] 在**user_text**中輸入您的請求,例如: ```shell 明天要從台北出發去普吉島,請規劃四天三夜的行程: 1. 行程需依據天氣狀況安排; 2. 確保整體行程合理、順暢; 3. 推薦的飯店需可實際預訂且預算為100~200美元 4. 參考農民曆資訊調整行程 5. 請以今天的匯率將預估的旅遊預算換算為台幣後填寫指定電子表單 6. 將終版本的行程產生為HTML檔案 ``` ## 三、 📝 對話紀錄:普吉島四天三夜行程規劃任務 --- ### 🧑‍💼 USER → Planner [`thread_To25qaIXIg9z8XlFoZ4pioVJ`] 明天要從台北出發去普吉島,請規劃四天三夜的行程: 1. 行程需依據天氣狀況安排; 2. 確保整體行程合理、順暢; 3. 推薦的飯店需可實際預訂且預算為100~200美元; 4. 參考農民曆資訊調整行程; 5. 請以今天的匯率將預估的旅遊預算換算為台幣後填寫指定電子表單; 6. 將終版本的行程產生為HTML檔案。 --- ### 🤖 [Step 0] Planner 回覆 好的,為了規劃一個合理且順暢的台北出發普吉島四天三夜行程,並滿足您的所有需求,我將依照以下步驟分配任務: 1. 先由 TravelPlanner 規劃初步行程架構。 2. 再由 WeatherAdvisor 根據最新天氣狀況調整每日活動。 3. RouteMaster 檢查並優化行程動線,確保順暢合理。 4. HotelFinder 推薦可預訂且符合預算的飯店,並參考農民曆資訊調整行程。 5. TripBudget 依據今天匯率,預估旅遊總預算並填寫指定電子表單。 6. 最後由 TravelStoryHTMLnImage 產生完整HTML檔案。 首先,請 TravelPlanner 規劃台北出發普吉島四天三夜的初步行程架構(不考慮天氣與住宿細節,僅列出每日主要活動與交通)。 [__TravelPlanner__] 規劃台北出發普吉島四天三夜的初步行程架構,包含每日主要活動與交通安排。 --- ### 🔁 任務轉交:Planner → TravelPlanner Handing off to 'TravelPlanner' with payload: '規劃台北出發普吉島四天三夜的初步行程架構,包含每日主要活動與交通安排。' --- ### 🤖 TravelPlanner 回覆 ``` 當然可以!以下是台北出發普吉島四天三夜的初步行程架構,包含每日主要活動、交通安排,以及每一天的實際日期(假設你9月10日從台北出發): ... ``` --- ### 🤖 [Step 1] Planner 回覆 TravelPlanner 已完成初步行程架構,接下來需要根據最新天氣狀況調整每日活動,確保行程安全且舒適。 [__WeatherAdvisor__] 根據普吉島未來四天的天氣預報,調整上述行程每日活動安排,並提供建議(如需更改海灘或戶外活動時間,請明確說明)。 --- ### 🔁 任務轉交:Planner → WeatherAdvisor Handing off to 'WeatherAdvisor' with payload: '根據普吉島未來四天的天氣預報,調整上述行程每日活動安排,並提供建議(如需更改海灘或戶外活動時間,請明確說明)。' --- ### 🛠️ 工具呼叫紀錄 - **Tool Call ID**: `call_nl63dX3Dz7jVOj5mDoOdcRgY` - **函式名稱**:`get_weather_forecast` - **參數**: ```json { "location_name": "Patong Beach", "start_date": "2025-09-10", "end_date": "2025-09-10" } ``` - **地理資訊**: - `location name`: Patong Beach - `latitude`: 7.8966319 - `longitude`: 98.2954295 - **天氣預報結果**: ```json { "temperature_2m_min": 25.4, "temperature_2m_max": 29.2, "rain_sum": 0.0, "precipitation_probability_max": 73, "precipitation_sum": 4.4, "weather_code": 53 } ``` --- ### 🤖 WeatherAdvisor 回覆 ``` 根據普吉島各主要地點未來四天的天氣預報,以下是針對原行程的調整與具體建議: ... ``` --- ### 🔁 Worker → Planner 回饋 (Speaker: WeatherAdvisor) 根據普吉島各主要地點未來四天的天氣預報,以下是針對原行程的調整與具體建議: --- ### 🤖 [Step 2] Planner 回覆 WeatherAdvisor 已根據天氣預報調整每日活動,建議以室內活動為主並彈性安排海灘及出海行程。接下來需要 RouteMaster 檢查並優化行程動線,確保交通安排合理且順暢。 [__RouteMaster__] 根據最新行程(含天氣調整),優化每日交通動線,並提供具體交通方式與時間建議。 --- ### 🔁 任務轉交:Planner → RouteMaster Handing off to 'RouteMaster' with payload: '根據最新行程(含天氣調整),優化每日交通動線,並提供具體交通方式與時間建議。' --- ### 🤖 RouteMaster 回覆 ``` 以下是根據天氣調整後的普吉島四天三夜行程,針對每日交通動線進行優化,並提供具體交通方式與時間建議: ... ``` --- ### 🔁 Worker → Planner 回饋 (Speaker: RouteMaster) 以下是根據天氣調整後的普吉島四天三夜行程,針對每日交通動線進行優化,並提供具體交通方式與時間建議: ... --- ### 🤖 [Step 3] Planner 回覆 RouteMaster 已優化行程動線並提供具體交通方式與時間建議。接下來需要 HotelFinder 推薦可預訂且符合預算(每晚100~200美元)的飯店,並參考農民曆資訊調整行程(如有不宜出行或特殊建議請明確說明)。 [__HotelFinder__] 推薦普吉島Patong Beach區可預訂且每晚100~200美元的飯店,並根據農民曆資訊調整行程(如有不宜出行或特殊建議請明確說明)。 --- ### 🔁 任務轉交:Planner → HotelFinder Handing off to 'HotelFinder' with payload: '推薦普吉島Patong Beach區可預訂且每晚100~200美元的飯店,並根據農民曆資訊調整行程(如有不宜出行或特殊建議請明確說明)。' --- ### 🤖 HotelFinder 回覆 ``` 根據您的需求,以下是普吉島Patong Beach區可預訂且每晚100~200美元的飯店推薦,並結合農民曆資訊給予行程調整建議: ``` ### 🔁 Worker → Planner 回饋 (Speaker: HotelFinder) 根據您的需求,以下是普吉島Patong Beach區可預訂且每晚100~200美元的飯店推薦,並結合農民曆資訊給予行程調整建議: ... --- ### 🤖 [Step 4] Planner 回覆 HotelFinder 已推薦可預訂且符合預算的飯店,並根據農民曆資訊確認行程安排皆宜出行,無需重大調整。接下來需要 TripBudget 依據今天匯率,預估旅遊總預算並換算為台幣,並填寫指定電子表單。 [__TripBudget__] 根據最新行程、住宿選擇(以Ocean Front View | Huge Condo為例)、交通與活動安排,預估總旅遊預算,並以今日匯率換算為台幣後填寫指定Microsoft Forms電子表單。 --- ### 🔁 任務轉交:Planner → TripBudget Handing off to 'TripBudget' with payload: '根據最新行程、住宿選擇(以Ocean Front View | Huge Condo為例)、交通與活動安排,預估總旅遊預算,並以今日匯率換算為台幣後填寫指定Microsoft Forms電子表單。' --- ### 🤖 TripBudget 回覆 ``` ### 普吉島四天三夜旅遊預算報告(以 Ocean Front View | Huge Condo 為例)! ... ``` --- ### 🤖 [Step 5] Planner 回覆 TripBudget 已完成預算估算並填寫指定電子表單。最後,請 TravelStoryHTMLnImage 將最終版本行程產生為HTML檔案,包含圖片與Google Maps地點。 [__TravelStoryHTMLnImage__] 產生普吉島四天三夜最終行程的HTML檔案,包含每日活動、飯店資訊、交通建議、圖片與Google Maps地點。 --- ### 🔁 任務轉交:Planner → TravelStoryHTMLnImage Handing off to 'TravelStoryHTMLnImage' with payload: '產生普吉島四天三夜最終行程的HTML檔案,包含每日活動、飯店資訊、交通建議、圖片與Google Maps地點。' --- ### 🛠️ 工具呼叫紀錄 - **Tool Call ID**: `call_abfxxBGaKtfJcYGmhgsoxUyu` #### 📍 `get_lat_long` ```json { "location_name": "Patong Tower, Patong Beach, Phuket" } ``` - 結果: - `latitude`: 7.89059 - `longitude`: 98.3981 #### 🖼️ `dalle` { "prompt": "A vibrant tropical travel collage showing Patong Beach, Phi Phi Islands, Thai food, and lively nightlife in Phuket, Thailand. The image should evoke a sense of adventure, relaxation, and exotic beauty." } --- ### 🤖 TravelStoryHTMLnImage 回覆 ``` Download Travel Plan ``` TERMINATE - ✅ blob upload 成功: ``` https://universalagstorage.blob.core.windows.net/files/assistant-6Z9fnNcMMvdiTktR7if8UH.html?se=2026-01-26T09%3A21%3A33Z&sp=r&sv=2025-07-05&sr=b&sig=MDmVRH2gu0rlb%2B85on4nLwLtUBl5LuPMXoCMaPj0vio%3D ``` --- ### 🤖 [Step 6] ✅ Planner claims finished [Finished] 您的普吉島四天三夜行程規劃已完成,包含天氣調整、交通動線優化、可預訂飯店推薦、農民曆建議、預算換算與表單填寫,以及精美HTML檔案(含圖片與Google Maps地點)。 請點擊以下連結下載您的完整旅遊計畫書: ``` (Speaker: TravelStoryHTMLnImage) ``` --- ## 四、 📝 普吉島四天三夜行程規劃最終版本 ![image](https://hackmd.io/_uploads/H1VPFON5gx.png)