alanchen1115 commited on
Commit
eec3bfc
·
verified ·
1 Parent(s): 2d3ad1f

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +37 -37
main.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  import io
3
  import PIL.Image
4
  import uvicorn
 
5
  from collections import defaultdict
6
  from fastapi import FastAPI, Request, Header, BackgroundTasks, HTTPException
7
  from fastapi.middleware.cors import CORSMiddleware
@@ -18,11 +19,16 @@ from linebot.models import (
18
  ImageMessage,
19
  )
20
 
21
- # --- 修正後的 LangChain 匯入路徑 ---
22
  from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
23
  from langchain_core.tools import tool
24
  from langchain_google_genai import ChatGoogleGenerativeAI
25
- from langchain.agents import AgentExecutor, create_tool_calling_agent
 
 
 
 
 
26
 
27
  # ==========================
28
  # 環境設定與工具函式
@@ -34,10 +40,8 @@ line_bot_api = LineBotApi(os.environ.get("CHANNEL_ACCESS_TOKEN"))
34
  line_handler = WebhookHandler(os.environ.get("CHANNEL_SECRET"))
35
 
36
  user_message_history = defaultdict(list)
37
-
38
  app = FastAPI()
39
 
40
- # 確保 static 資料夾存在
41
  if not os.path.exists("static"):
42
  os.makedirs("static")
43
  app.mount("/static", StaticFiles(directory="static"), name="static")
@@ -53,7 +57,7 @@ app.add_middleware(
53
  def get_image_url_from_line(message_id):
54
  try:
55
  message_content = line_bot_api.get_message_content(message_id)
56
- file_path = f"static/{message_id}.png" # 改存到 static 方便讀取
57
  with open(file_path, "wb") as f:
58
  for chunk in message_content.iter_content():
59
  f.write(chunk)
@@ -78,7 +82,6 @@ def get_previous_message(user_id):
78
  def generate_and_upload_image(prompt: str) -> str:
79
  """根據文字提示生成圖片。"""
80
  try:
81
- # 修正模型名稱:目前最新穩定版為 imagen-3
82
  response = genai_client.models.generate_content(
83
  model="imagen-3.0-generate-001",
84
  contents=prompt,
@@ -96,10 +99,9 @@ def generate_and_upload_image(prompt: str) -> str:
96
  file_name = f"static/{os.urandom(8).hex()}.png"
97
  image.save(file_name, format="PNG")
98
 
99
- # 修正 URL 拼接邏輯
100
  base_url = os.getenv("HF_SPACE", "http://localhost:7860").rstrip("/")
101
- image_url = f"{base_url}/{file_name}"
102
- return image_url
103
  return "圖片生成失敗:模型未回傳數據。"
104
  except Exception as e:
105
  return f"圖片生成失敗: {e}"
@@ -110,11 +112,10 @@ def analyze_image_with_text(image_path: str, user_text: str) -> str:
110
  try:
111
  if not os.path.exists(image_path):
112
  return "錯誤:找不到該圖片檔案。"
113
-
114
  img_user = PIL.Image.open(image_path)
115
- # 修正模型名稱:目前為 gemini-1.5-flash 或 gemini-2.0-flash-exp
116
  response = genai_client.models.generate_content(
117
- model="gemini-3-flash-preview",
118
  contents=[img_user, user_text]
119
  )
120
  return response.text if response.text else "Gemini 沒答案!"
@@ -125,8 +126,7 @@ def analyze_image_with_text(image_path: str, user_text: str) -> str:
125
  # LangChain 代理人設定
126
  # ==========================
127
  tools = [generate_and_upload_image, analyze_image_with_text]
128
- # 修正模型名稱
129
- llm = ChatGoogleGenerativeAI(model="gemini-3-flash-preview", temperature=0.2)
130
 
131
  prompt_template = ChatPromptTemplate.from_messages([
132
  ("system", "你是一個強大的助理。如果生成了圖片,請直接給出 URL。"),
@@ -158,20 +158,22 @@ async def webhook(request: Request, background_tasks: BackgroundTasks, x_line_si
158
  def handle_message(event):
159
  user_id = event.source.user_id
160
 
161
- if event.message.type == "image":
 
162
  image_path = get_image_url_from_line(event.message.id)
163
  if image_path:
164
  store_user_message(user_id, "image", image_path)
165
- line_bot_api.reply_message(event.reply_token, TextSendMessage(text="收到圖片了!請問你想對這張圖做什麼分析?"))
166
 
167
- elif event.message.type == "text":
 
168
  user_text = event.message.text
169
  previous_message = get_previous_message(user_id)
170
 
171
  if previous_message["type"] == "image":
172
  image_path = previous_message["content"]
173
- agent_input = {"input": f"請分析這張圖片 {image_path},問題:{user_text}"}
174
- user_message_history[user_id].pop() # 用完即丟
175
  else:
176
  agent_input = {"input": user_text}
177
 
@@ -179,25 +181,23 @@ def handle_message(event):
179
  response = agent_executor.invoke(agent_input)
180
  out = response["output"]
181
 
182
- if "http" in out and (".png" in out or ".jpg" in out):
183
- # 簡單提取第一個 URL
184
- import re
185
- urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', out)
186
- if urls:
187
- image_url = urls[0]
188
- line_bot_api.reply_message(
189
- event.reply_token,
190
- [
191
- TextSendMessage(text="這是為你生成的圖片:"),
192
- ImageSendMessage(original_content_url=image_url, preview_image_url=image_url)
193
- ]
194
- )
195
- return
196
-
197
- line_bot_api.reply_message(event.reply_token, TextSendMessage(text=out))
198
 
 
 
 
 
 
 
 
 
 
 
199
  except Exception as e:
200
- line_bot_api.reply_message(event.reply_token, TextSendMessage(text=f"系統忙碌中,請稍後再試。"))
 
201
 
202
  if __name__ == "__main__":
203
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
2
  import io
3
  import PIL.Image
4
  import uvicorn
5
+ import re
6
  from collections import defaultdict
7
  from fastapi import FastAPI, Request, Header, BackgroundTasks, HTTPException
8
  from fastapi.middleware.cors import CORSMiddleware
 
19
  ImageMessage,
20
  )
21
 
22
+ # --- 核心修正:改用絕對路徑匯入 AgentExecutor ---
23
  from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
24
  from langchain_core.tools import tool
25
  from langchain_google_genai import ChatGoogleGenerativeAI
26
+ # 如果 langchain.agents 匯入失敗,這裡改從 .agent 模組直接抓取
27
+ try:
28
+ from langchain.agents import create_tool_calling_agent, AgentExecutor
29
+ except ImportError:
30
+ from langchain.agents.agent import AgentExecutor
31
+ from langchain.agents import create_tool_calling_agent
32
 
33
  # ==========================
34
  # 環境設定與工具函式
 
40
  line_handler = WebhookHandler(os.environ.get("CHANNEL_SECRET"))
41
 
42
  user_message_history = defaultdict(list)
 
43
  app = FastAPI()
44
 
 
45
  if not os.path.exists("static"):
46
  os.makedirs("static")
47
  app.mount("/static", StaticFiles(directory="static"), name="static")
 
57
  def get_image_url_from_line(message_id):
58
  try:
59
  message_content = line_bot_api.get_message_content(message_id)
60
+ file_path = f"static/{message_id}.png"
61
  with open(file_path, "wb") as f:
62
  for chunk in message_content.iter_content():
63
  f.write(chunk)
 
82
  def generate_and_upload_image(prompt: str) -> str:
83
  """根據文字提示生成圖片。"""
84
  try:
 
85
  response = genai_client.models.generate_content(
86
  model="imagen-3.0-generate-001",
87
  contents=prompt,
 
99
  file_name = f"static/{os.urandom(8).hex()}.png"
100
  image.save(file_name, format="PNG")
101
 
 
102
  base_url = os.getenv("HF_SPACE", "http://localhost:7860").rstrip("/")
103
+ # 如果在本地執行,請確保 URL 格式正確
104
+ return f"{base_url}/{file_name}"
105
  return "圖片生成失敗:模型未回傳數據。"
106
  except Exception as e:
107
  return f"圖片生成失敗: {e}"
 
112
  try:
113
  if not os.path.exists(image_path):
114
  return "錯誤:找不到該圖片檔案。"
 
115
  img_user = PIL.Image.open(image_path)
116
+ # 修正:目前最新為 gemini-2.0-flash 或 1.5-flash
117
  response = genai_client.models.generate_content(
118
+ model="gemini-1.5-flash",
119
  contents=[img_user, user_text]
120
  )
121
  return response.text if response.text else "Gemini 沒答案!"
 
126
  # LangChain 代理人設定
127
  # ==========================
128
  tools = [generate_and_upload_image, analyze_image_with_text]
129
+ llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0.2)
 
130
 
131
  prompt_template = ChatPromptTemplate.from_messages([
132
  ("system", "你是一個強大的助理。如果生成了圖片,請直接給出 URL。"),
 
158
  def handle_message(event):
159
  user_id = event.source.user_id
160
 
161
+ # 處理圖片訊息
162
+ if isinstance(event.message, ImageMessage):
163
  image_path = get_image_url_from_line(event.message.id)
164
  if image_path:
165
  store_user_message(user_id, "image", image_path)
166
+ line_bot_api.reply_message(event.reply_token, TextSendMessage(text="收到圖片了!請問你想分析什麼?"))
167
 
168
+ # 處理文字訊息
169
+ elif isinstance(event.message, TextMessage):
170
  user_text = event.message.text
171
  previous_message = get_previous_message(user_id)
172
 
173
  if previous_message["type"] == "image":
174
  image_path = previous_message["content"]
175
+ agent_input = {"input": f"請分析圖片 {image_path},問題:{user_text}"}
176
+ user_message_history[user_id].pop()
177
  else:
178
  agent_input = {"input": user_text}
179
 
 
181
  response = agent_executor.invoke(agent_input)
182
  out = response["output"]
183
 
184
+ # URL 偵測邏輯
185
+ urls = re.findall(r'https?://[^\s<>"]+|www\.[^\s<>"]+', out)
186
+ image_url = next((u for u in urls if any(ext in u.lower() for ext in ['.png', '.jpg', '.jpeg'])), None)
 
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
+ if image_url:
189
+ line_bot_api.reply_message(
190
+ event.reply_token,
191
+ [
192
+ TextSendMessage(text="這是生成的圖片:"),
193
+ ImageSendMessage(original_content_url=image_url, preview_image_url=image_url)
194
+ ]
195
+ )
196
+ else:
197
+ line_bot_api.reply_message(event.reply_token, TextSendMessage(text=out))
198
  except Exception as e:
199
+ print(f"Agent Error: {e}")
200
+ line_bot_api.reply_message(event.reply_token, TextSendMessage(text="處理訊息時發生錯誤。"))
201
 
202
  if __name__ == "__main__":
203
+ uvicorn.run(app, host="0.0.0.0", port=7860)