Spaces:
Running
Running
Commit ·
dddc990
1
Parent(s): e9b2abf
feat: add toolmessage result
Browse files- services/agents.py +30 -43
- services/linebot.py +12 -9
services/agents.py
CHANGED
|
@@ -6,18 +6,9 @@ from dotenv import load_dotenv # 匯入 dotenv 以載入 .env 環境變數檔案
|
|
| 6 |
import json # 匯入 json 庫用於序列化
|
| 7 |
|
| 8 |
# LangChain 相關匯入
|
| 9 |
-
#from langchain_core.prompts import ChatPromptTemplate # 匯入 LangChain 的聊天提示模板
|
| 10 |
-
#from langchain_core.tools import tool # 匯入 LangChain 的工具裝飾器
|
| 11 |
-
#from langchain_google_genai import ChatGoogleGenerativeAI # 匯入 LangChain 的 Google GenAI 聊天模型
|
| 12 |
-
#from langchain.agents import create_tool_calling_agent
|
| 13 |
-
#from langchain.agents import AgentExecutor # (若此行仍錯誤,則要改用 Runnable 方式)
|
| 14 |
-
#from langchain.agents import initialize_agent
|
| 15 |
-
#from langchain.agents import AgentType
|
| 16 |
-
|
| 17 |
from langchain.agents import create_agent
|
| 18 |
-
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
| 19 |
from langchain.tools import tool
|
| 20 |
-
from langchain.messages import
|
| 21 |
|
| 22 |
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 23 |
|
|
@@ -218,23 +209,6 @@ llm = ChatGoogleGenerativeAI(
|
|
| 218 |
temperature=0.2
|
| 219 |
)
|
| 220 |
|
| 221 |
-
# 建立提示模板
|
| 222 |
-
#prompt_template = ChatPromptTemplate([
|
| 223 |
-
# ("system",
|
| 224 |
-
# """
|
| 225 |
-
# 你是一個強大的圖像生成、圖像去模糊與問答助理,可以根據用戶的請求使用提供的工具。
|
| 226 |
-
# ### 核心輸出規範
|
| 227 |
-
# * **結果呈現**:當你執行以下任一圖像處理工具成功後,你最終的回答 output **必須包含該 URL 的完整資訊**:
|
| 228 |
-
# * `generate_and_upload_image`
|
| 229 |
-
# * `deblur_image_from_url` (或其他任何產生圖像輸出的工具)
|
| 230 |
-
#
|
| 231 |
-
# * **錯誤處理**:如果工具有產生錯誤訊息,請解讀錯誤並以自然語言回應給用戶。
|
| 232 |
-
# """
|
| 233 |
-
# ), # 系統提示 (System Prompt)
|
| 234 |
-
# ("user", "{input}"), # 用戶輸入的佔位符
|
| 235 |
-
# ("placeholder", "{agent_scratchpad}"), # 代理人思考過程的佔位符
|
| 236 |
-
#])
|
| 237 |
-
|
| 238 |
# ✅ 建立 Prompt (新版語法)
|
| 239 |
sys_prompt = """
|
| 240 |
你是一個強大的圖像生成、圖像去模糊與問答助理,可以根據用戶的請求使用提供的工具。
|
|
@@ -246,12 +220,6 @@ sys_prompt = """
|
|
| 246 |
* **錯誤處理**:如果工具有產生錯誤訊息,請解讀錯誤並以自然語言回應給用戶。
|
| 247 |
"""
|
| 248 |
|
| 249 |
-
# 建立工具調用代理人 (Tool Calling Agent)
|
| 250 |
-
#agent = create_tool_calling_agent(llm, tools, prompt_template)
|
| 251 |
-
# 建立代理人執行器 (Agent Executor)
|
| 252 |
-
#agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # verbose=True 會在終端印出代理人的思考過程
|
| 253 |
-
# ✅ 使用 initialize_agent 取代 create_tool_calling_agent + AgentExecutor
|
| 254 |
-
|
| 255 |
# --- 4. 建立代理人與執行器 ---
|
| 256 |
# 建立工具調用代理人 (Tool Calling Agent)
|
| 257 |
agent = create_agent(
|
|
@@ -260,20 +228,39 @@ agent = create_agent(
|
|
| 260 |
system_prompt=sys_prompt
|
| 261 |
)
|
| 262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
def run_agent(user_input: str):
|
| 264 |
"""呼叫此函式來執行 Agent"""
|
| 265 |
-
#human_msg = HumanMessage( user_input )
|
| 266 |
-
#sys_msg = SystemMessage(sys_prompt)
|
| 267 |
-
#messages = [
|
| 268 |
-
# sys_msg,
|
| 269 |
-
# human_msg
|
| 270 |
-
#]
|
| 271 |
print(f"UserInput:{user_input}")
|
| 272 |
result = agent.invoke({
|
| 273 |
"messages": [{"role": "user", "content": user_input }]
|
| 274 |
})
|
| 275 |
-
|
| 276 |
print(f"result:{result}")
|
| 277 |
-
return {
|
| 278 |
-
"output": result["messages"][-1].content
|
| 279 |
-
}
|
|
|
|
| 6 |
import json # 匯入 json 庫用於序列化
|
| 7 |
|
| 8 |
# LangChain 相關匯入
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
from langchain.agents import create_agent
|
|
|
|
| 10 |
from langchain.tools import tool
|
| 11 |
+
from langchain.messages import AIMessage, HumanMessage, ToolMessage
|
| 12 |
|
| 13 |
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 14 |
|
|
|
|
| 209 |
temperature=0.2
|
| 210 |
)
|
| 211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
# ✅ 建立 Prompt (新版語法)
|
| 213 |
sys_prompt = """
|
| 214 |
你是一個強大的圖像生成、圖像去模糊與問答助理,可以根據用戶的請求使用提供的工具。
|
|
|
|
| 220 |
* **錯誤處理**:如果工具有產生錯誤訊息,請解讀錯誤並以自然語言回應給用戶。
|
| 221 |
"""
|
| 222 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
# --- 4. 建立代理人與執行器 ---
|
| 224 |
# 建立工具調用代理人 (Tool Calling Agent)
|
| 225 |
agent = create_agent(
|
|
|
|
| 228 |
system_prompt=sys_prompt
|
| 229 |
)
|
| 230 |
|
| 231 |
+
def format_agent_result(result):
|
| 232 |
+
output = {
|
| 233 |
+
"user": None,
|
| 234 |
+
"tool_call": None,
|
| 235 |
+
"tool_result": None,
|
| 236 |
+
"final_response": None
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
for msg in result["messages"]:
|
| 240 |
+
if isinstance(msg, HumanMessage):
|
| 241 |
+
output["user"] = msg.content
|
| 242 |
+
|
| 243 |
+
elif isinstance(msg, AIMessage) and msg.additional_kwargs.get("function_call"):
|
| 244 |
+
fn = msg.additional_kwargs["function_call"]
|
| 245 |
+
output["tool_call"] = {
|
| 246 |
+
"name": fn["name"],
|
| 247 |
+
"arguments": fn["arguments"]
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
elif isinstance(msg, ToolMessage):
|
| 251 |
+
output["tool_result"] = json.loads(msg.content)
|
| 252 |
+
|
| 253 |
+
elif isinstance(msg, AIMessage) and not msg.additional_kwargs.get("function_call"):
|
| 254 |
+
output["final_response"] = msg.content
|
| 255 |
+
|
| 256 |
+
return output
|
| 257 |
+
|
| 258 |
def run_agent(user_input: str):
|
| 259 |
"""呼叫此函式來執行 Agent"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
print(f"UserInput:{user_input}")
|
| 261 |
result = agent.invoke({
|
| 262 |
"messages": [{"role": "user", "content": user_input }]
|
| 263 |
})
|
| 264 |
+
|
| 265 |
print(f"result:{result}")
|
| 266 |
+
return { "output": format_agent_result( result ) }
|
|
|
|
|
|
services/linebot.py
CHANGED
|
@@ -141,18 +141,18 @@ def handle_message(event):
|
|
| 141 |
response = run_agent(agent_input)
|
| 142 |
# Agent 的輸出是 JSON 字串 (無論成功或失敗)
|
| 143 |
out_str = response["output"]
|
| 144 |
-
|
| 145 |
-
|
| 146 |
|
| 147 |
-
if "error" in
|
| 148 |
# 3A. 處理錯誤情況 (例如:圖片下載失敗、API 錯誤)
|
| 149 |
-
error_msg =
|
| 150 |
reply_text = f"🚫 圖片工具執行失敗:\n{error_msg}"
|
| 151 |
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=reply_text))
|
| 152 |
-
elif "image_url" in
|
| 153 |
# 3B. 處理成功情況 (帶有圖片 URL,例如:圖片生成或去模糊工具)
|
| 154 |
-
image_url =
|
| 155 |
-
text_result =
|
| 156 |
|
| 157 |
# Line 要求圖片 URL 必須是 HTTPS
|
| 158 |
# 由於 HF_SPACE 預設是 https,這裡做一個保險轉換
|
|
@@ -170,11 +170,14 @@ def handle_message(event):
|
|
| 170 |
]
|
| 171 |
)
|
| 172 |
|
| 173 |
-
elif "text_result" in
|
| 174 |
# 3C. 處理純文字結果 (例如:多模態分析工具)
|
| 175 |
-
text_result =
|
| 176 |
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=text_result))
|
| 177 |
|
|
|
|
|
|
|
|
|
|
| 178 |
else:
|
| 179 |
# 3D. 處理意外的 JSON 結構
|
| 180 |
line_bot_api.reply_message(
|
|
|
|
| 141 |
response = run_agent(agent_input)
|
| 142 |
# Agent 的輸出是 JSON 字串 (無論成功或失敗)
|
| 143 |
out_str = response["output"]
|
| 144 |
+
tool_result = out_str.get("tool_result", {})
|
| 145 |
+
final_response = out_str.get("final_response")
|
| 146 |
|
| 147 |
+
if "error" in tool_result:
|
| 148 |
# 3A. 處理錯誤情況 (例如:圖片下載失敗、API 錯誤)
|
| 149 |
+
error_msg = tool_result["error"]
|
| 150 |
reply_text = f"🚫 圖片工具執行失敗:\n{error_msg}"
|
| 151 |
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=reply_text))
|
| 152 |
+
elif "image_url" in tool_result:
|
| 153 |
# 3B. 處理成功情況 (帶有圖片 URL,例如:圖片生成或去模糊工具)
|
| 154 |
+
image_url = tool_result["image_url"]
|
| 155 |
+
text_result = tool_result.get("text_result", "圖片處理完成。")
|
| 156 |
|
| 157 |
# Line 要求圖片 URL 必須是 HTTPS
|
| 158 |
# 由於 HF_SPACE 預設是 https,這裡做一個保險轉換
|
|
|
|
| 170 |
]
|
| 171 |
)
|
| 172 |
|
| 173 |
+
elif "text_result" in tool_result:
|
| 174 |
# 3C. 處理純文字結果 (例如:多模態分析工具)
|
| 175 |
+
text_result = tool_result["text_result"]
|
| 176 |
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=text_result))
|
| 177 |
|
| 178 |
+
elif final_response:
|
| 179 |
+
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=final_response))
|
| 180 |
+
|
| 181 |
else:
|
| 182 |
# 3D. 處理意外的 JSON 結構
|
| 183 |
line_bot_api.reply_message(
|