Enzo886 commited on
Commit
dce5b10
·
verified ·
1 Parent(s): 2c540e2

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +54 -28
main.py CHANGED
@@ -8,15 +8,19 @@ from linebot.exceptions import InvalidSignatureError
8
  from linebot.models import MessageEvent, TextMessage, TextSendMessage, ImageSendMessage, AudioMessage
9
  from dotenv import load_dotenv
10
 
11
- # Load environment variables from .env file
12
  load_dotenv()
13
 
14
- # Logging configuration
15
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
16
 
17
 
18
- # --- 1. Configuration ---
19
  def configure_gemini():
 
 
 
 
20
  try:
21
  genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
22
  generation_config = genai.types.GenerationConfig(
@@ -26,38 +30,42 @@ def configure_gemini():
26
  "gemini-2.0-flash-exp",
27
  system_instruction="你是咖啡廳員工,請使用親切的招呼語做為開頭,然後以爽朗愉悅的口氣回答問題。",
28
  )
29
- logging.info("Gemini model configured successfully.")
30
  return model, generation_config
31
  except Exception as e:
32
- logging.error(f"Error configuring Gemini: {e}")
33
  raise
34
 
35
 
36
  def configure_line_bot():
 
 
 
 
37
  try:
38
  line_bot_api = LineBotApi(os.getenv("CHANNEL_ACCESS_TOKEN"))
39
  line_handler = WebhookHandler(os.getenv("CHANNEL_SECRET"))
40
- logging.info("Line Bot API configured successfully.")
41
  return line_bot_api, line_handler
42
  except Exception as e:
43
- logging.error(f"Error configuring Line Bot API: {e}")
44
  raise
45
 
46
- # Initialize configurations
47
  try:
48
  model, generation_config = configure_gemini()
49
  line_bot_api, line_handler = configure_line_bot()
50
  except Exception as e:
51
- logging.critical(f"Failed to initialize configurations: {e}")
52
- exit(1) # Exit if critical configuration fails
53
 
54
- # Default talking state from environment variable
55
  working_status = os.getenv("DEFALUT_TALKING", default="true").lower() == "true"
56
 
57
- # --- 2. FastAPI App ---
58
  app = FastAPI()
59
 
60
- # Setup CORS
61
  app.add_middleware(
62
  CORSMiddleware,
63
  allow_origins=["*"],
@@ -66,9 +74,12 @@ app.add_middleware(
66
  allow_headers=["*"],
67
  )
68
 
69
- # --- 3. Routes ---
70
  @app.get("/")
71
  def root():
 
 
 
72
  return {"title": "Line Bot"}
73
 
74
 
@@ -76,22 +87,30 @@ def root():
76
  async def webhook(
77
  request: Request, background_tasks: BackgroundTasks, x_line_signature=Header(None)
78
  ):
 
 
 
 
79
  body = await request.body()
80
  try:
81
  background_tasks.add_task(
82
  line_handler.handle, body.decode("utf-8"), x_line_signature
83
  )
84
  except InvalidSignatureError:
85
- logging.warning("Invalid signature received.")
86
- raise HTTPException(status_code=400, detail="Invalid signature")
87
  return "ok"
88
 
89
- # --- 4. Chat Session Management ---
90
  chat_sessions = {}
91
 
92
  def get_or_create_chat_session(user_id: str):
 
 
 
 
93
  if user_id not in chat_sessions:
94
- logging.info(f"Creating new chat session for user: {user_id}")
95
  chat_sessions[user_id] = model.start_chat(
96
  history=[
97
  {
@@ -107,6 +126,9 @@ def get_or_create_chat_session(user_id: str):
107
  return chat_sessions[user_id]
108
 
109
  def handle_text_message(event):
 
 
 
110
  global working_status
111
 
112
  user_id = event.source.user_id
@@ -114,40 +136,44 @@ def handle_text_message(event):
114
  line_bot_api.reply_message(event.reply_token, TextSendMessage(text="Bye!"))
115
  if user_id in chat_sessions:
116
  del chat_sessions[user_id]
117
- logging.info(f"Chat session deleted for user: {user_id}")
118
  return
119
 
120
  if not working_status:
121
- logging.info("Bot is not in working status, ignoring message.")
122
  return
123
 
124
  try:
125
  prompt = event.message.text
126
- logging.info(f"Received user prompt: {prompt}, user: {user_id}")
127
  chat_session = get_or_create_chat_session(user_id)
128
  response = chat_session.send_message(prompt)
129
  if response.text:
130
  out = response.text
131
- logging.info(f"Gemini response: {out}, user: {user_id}")
132
  else:
133
  out = "Gemini 沒答案!請換個說法!"
134
- logging.warning(f"Gemini returned no text response for user: {user_id}")
135
  except Exception as e:
136
  out = "Gemini 執行出錯!請換個說法!"
137
- logging.error(f"Gemini error: {e}, user: {user_id}")
138
 
139
  line_bot_api.reply_message(event.reply_token, TextSendMessage(text=out))
140
 
141
  @line_handler.add(MessageEvent, message=TextMessage)
142
  def handle_message(event):
 
 
 
 
143
  if event.type != "message" or event.message.type != "text":
144
- logging.warning("Event type error: not a text message.")
145
- line_bot_api.reply_message(event.reply_token, TextSendMessage(text="Event type error: not a text message."))
146
  return
147
 
148
  handle_text_message(event)
149
 
150
- # --- 5. Start App ---
151
  if __name__ == "__main__":
152
  import uvicorn
153
 
 
8
  from linebot.models import MessageEvent, TextMessage, TextSendMessage, ImageSendMessage, AudioMessage
9
  from dotenv import load_dotenv
10
 
11
+ # .env 檔案載入環境變數
12
  load_dotenv()
13
 
14
+ # 設定日誌記錄
15
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', encoding='utf-8')
16
 
17
 
18
+ # --- 1. 配置設定 ---
19
  def configure_gemini():
20
+ """
21
+ 配置 Google Gemini 模型
22
+ 設定 API 金鑰、生成參數和模型
23
+ """
24
  try:
25
  genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
26
  generation_config = genai.types.GenerationConfig(
 
30
  "gemini-2.0-flash-exp",
31
  system_instruction="你是咖啡廳員工,請使用親切的招呼語做為開頭,然後以爽朗愉悅的口氣回答問題。",
32
  )
33
+ logging.info("Gemini 模型配置完成.")
34
  return model, generation_config
35
  except Exception as e:
36
+ logging.error(f"Gemini 模型配置錯誤: {e}")
37
  raise
38
 
39
 
40
  def configure_line_bot():
41
+ """
42
+ 配置 Line Bot API
43
+ 設定 Channel Access Token 和 Channel Secret
44
+ """
45
  try:
46
  line_bot_api = LineBotApi(os.getenv("CHANNEL_ACCESS_TOKEN"))
47
  line_handler = WebhookHandler(os.getenv("CHANNEL_SECRET"))
48
+ logging.info("Line Bot API 配置完成.")
49
  return line_bot_api, line_handler
50
  except Exception as e:
51
+ logging.error(f"Line Bot API 配置錯誤: {e}")
52
  raise
53
 
54
+ # 初始化配置
55
  try:
56
  model, generation_config = configure_gemini()
57
  line_bot_api, line_handler = configure_line_bot()
58
  except Exception as e:
59
+ logging.critical(f"初始化配置失敗: {e}")
60
+ exit(1) # 如果配置失敗,則終止程式
61
 
62
+ # 從環境變數取得是否啟用對話模式,預設為 true
63
  working_status = os.getenv("DEFALUT_TALKING", default="true").lower() == "true"
64
 
65
+ # --- 2. FastAPI 應用程式 ---
66
  app = FastAPI()
67
 
68
+ # 設定 CORS,允許跨域請求
69
  app.add_middleware(
70
  CORSMiddleware,
71
  allow_origins=["*"],
 
74
  allow_headers=["*"],
75
  )
76
 
77
+ # --- 3. 路由設定 ---
78
  @app.get("/")
79
  def root():
80
+ """
81
+ 處理根路徑請求,返回 Line Bot 的標題
82
+ """
83
  return {"title": "Line Bot"}
84
 
85
 
 
87
  async def webhook(
88
  request: Request, background_tasks: BackgroundTasks, x_line_signature=Header(None)
89
  ):
90
+ """
91
+ 處理 Line Webhook 請求
92
+ 接收 Line 的訊息並驗證簽章,然後將訊息處理加入背景任務
93
+ """
94
  body = await request.body()
95
  try:
96
  background_tasks.add_task(
97
  line_handler.handle, body.decode("utf-8"), x_line_signature
98
  )
99
  except InvalidSignatureError:
100
+ logging.warning("收到無效的簽章.")
101
+ raise HTTPException(status_code=400, detail="無效的簽章")
102
  return "ok"
103
 
104
+ # --- 4. 對話 Session 管理 ---
105
  chat_sessions = {}
106
 
107
  def get_or_create_chat_session(user_id: str):
108
+ """
109
+ 取得或建立特定使用者的對話 Session
110
+ 如果不存在,則建立一個新的 Session
111
+ """
112
  if user_id not in chat_sessions:
113
+ logging.info(f"為使用者 {user_id} 建立新的對話 Session")
114
  chat_sessions[user_id] = model.start_chat(
115
  history=[
116
  {
 
126
  return chat_sessions[user_id]
127
 
128
  def handle_text_message(event):
129
+ """
130
+ 處理文字訊息,取得使用者輸入,並回覆 Gemini 模型的訊息
131
+ """
132
  global working_status
133
 
134
  user_id = event.source.user_id
 
136
  line_bot_api.reply_message(event.reply_token, TextSendMessage(text="Bye!"))
137
  if user_id in chat_sessions:
138
  del chat_sessions[user_id]
139
+ logging.info(f"使用者 {user_id} 說再見,已刪除對話 Session")
140
  return
141
 
142
  if not working_status:
143
+ logging.info("對話模式關閉,忽略訊息.")
144
  return
145
 
146
  try:
147
  prompt = event.message.text
148
+ logging.info(f"收到使用者 {user_id} 的訊息: {prompt}")
149
  chat_session = get_or_create_chat_session(user_id)
150
  response = chat_session.send_message(prompt)
151
  if response.text:
152
  out = response.text
153
+ logging.info(f"Gemini 回覆使用者 {user_id}: {out}")
154
  else:
155
  out = "Gemini 沒答案!請換個說法!"
156
+ logging.warning(f"Gemini 沒有回覆文字內容給使用者 {user_id}")
157
  except Exception as e:
158
  out = "Gemini 執行出錯!請換個說法!"
159
+ logging.error(f"Gemini 發生錯誤 (使用者: {user_id}): {e}")
160
 
161
  line_bot_api.reply_message(event.reply_token, TextSendMessage(text=out))
162
 
163
  @line_handler.add(MessageEvent, message=TextMessage)
164
  def handle_message(event):
165
+ """
166
+ Line Bot 訊息處理的主要函式
167
+ 驗證訊息類型,然後將文字訊息轉發給處理函數
168
+ """
169
  if event.type != "message" or event.message.type != "text":
170
+ logging.warning("事件類型錯誤:不是文字訊息.")
171
+ line_bot_api.reply_message(event.reply_token, TextSendMessage(text="事件類型錯誤:不是文字訊息。"))
172
  return
173
 
174
  handle_text_message(event)
175
 
176
+ # --- 5. 啟動應用程式 ---
177
  if __name__ == "__main__":
178
  import uvicorn
179