File size: 6,890 Bytes
55b1be9 4123c19 d244aaf d0e2bcd 217ceea f91846a 4123c19 d244aaf 6fa6ba2 f91846a 2085249 b6cee01 49db02d d390efa 98dc21e 954f7c4 98dc21e d0e2bcd 98dc21e b328a8c d0e2bcd 78d28b2 4123c19 1ce0901 98dc21e 31979c9 4123c19 98dc21e 55b1be9 98dc21e 4123c19 55b1be9 df5bf2a 55b1be9 4123c19 55b1be9 6482098 a7c9894 2cf7795 4123c19 6482098 4123c19 0a52d39 3a2e91a 4123c19 34287b9 3a2e91a 4123c19 34287b9 0385c62 4123c19 8ff7523 4123c19 883cea6 b92f1fc 8b31299 b1adecf b92f1fc 8ff7523 d390efa b92f1fc e5255b6 3e627e5 4123c19 fac1691 3e8b9b3 b6cee01 7cf743a 35e1290 31979c9 fac1691 35e1290 fac1691 f24d293 fac1691 f24d293 fac1691 f24d293 fac1691 f24d293 b92f1fc d390efa b92f1fc ab50743 b92f1fc c0ca9ac 7c5eecf a7a62b4 735a8eb d546491 4123c19 d390efa c0ca9ac b92f1fc c0ca9ac b92f1fc c0ca9ac b92f1fc 78d28b2 b92f1fc c0ca9ac b92f1fc 8b31299 b92f1fc c0ca9ac 4123c19 3bf6983 4123c19 98dc21e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
from fastapi.middleware.cors import CORSMiddleware
from fastapi import FastAPI, Request, Header, BackgroundTasks, HTTPException, status
import google.generativeai as genai_gen
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage, ImageSendMessage, AudioMessage, ImageMessage
import json, os
import io
import PIL.Image
from imgurpython import ImgurClient
from Image_text_generation import Image_text_Generator
from Uploading_images import get_image_url, store_user_message, analyze_with_gemini, get_previous_message
#==========================
# API 金鑰
#==========================
# 設定 Google AI API 金鑰
google_api = os.environ["GOOGLE_API_KEY"]
genai_gen.configure(api_key=google_api)
# 設定生成文字的參數
generation_config = genai_gen.types.GenerationConfig(max_output_tokens=1000, temperature=0.2, top_p=0.5, top_k=16) #2048
# 使用 gemini-2.0-flash-exp 模型
model = genai_gen.GenerativeModel('gemini-2.0-flash-exp', system_instruction="主要用繁體中文回答,但如果用戶使用詢問英文問題,就用英文回應。你現在是個專業助理,職稱為OPEN小助理,個性活潑、樂觀,願意回答所有問題", generation_config=generation_config)
# 設定 Line Bot 的 API 金鑰和秘密金鑰
line_bot_api = LineBotApi(os.environ["CHANNEL_ACCESS_TOKEN"])
line_handler = WebhookHandler(os.environ["CHANNEL_SECRET"])
# 設定 Imgur 的 API
client_id = os.environ.get("IMGUR_CLIENT_ID")
client_secret = os.environ.get("IMGUR_CLIENT_SECRET")
access_token = os.environ.get("IMGUR_ACCESS_TOKEN")
refresh_token = os.environ.get("IMGUR_REFRESH_TOKEN")
# 設定是否正在與使用者交談
working_status = os.getenv("DEFALUT_TALKING", default = "true").lower() == "true"
# 建立 FastAPI 應用程式
app = FastAPI()
# 設定 CORS,允許跨域請求
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 處理根路徑請求
@app.get("/")
def root():
return {"title": "Line Bot"}
# 處理 Line Webhook 請求
@app.post("/webhook")
async def webhook(
request: Request,
background_tasks: BackgroundTasks,
x_line_signature=Header(None),
):
# 取得請求內容
body = await request.body()
try:
# 將處理 Line 事件的任務加入背景工作
background_tasks.add_task(
line_handler.handle, body.decode("utf-8"), x_line_signature
)
except InvalidSignatureError:
# 處理無效的簽章錯誤
raise HTTPException(status_code=400, detail="Invalid signature")
return "ok"
#==========================
# 主程式(圖片與文字)
#==========================
# 建立 chat_sessions 字典
chat_sessions = {}
@line_handler.add(MessageEvent, message=(ImageMessage, TextMessage))
def handle_image_message(event):
user_id = event.source.user_id
chat = chat_sessions.get(user_id) or model.start_chat(history=[])
chat_sessions[user_id] = chat
# ========
# 生成圖片
# ========
user_text = event.message.text if event.message.type == "text" else None
image_url = None
if user_text and user_text.startswith("生成圖片"):
prompt = user_text.replace("生成圖片", "").strip()
# 先立即回覆避免token過期
line_bot_api.reply_message(event.reply_token, TextSendMessage(text="圖片生成中~ 請稍候.....✨"))
imgur = ImgurClient(client_id, client_secret, access_token, refresh_token)
image_generator = Image_text_Generator(imgur)
# 生成圖片
image_binary = image_generator.generate_image_with_gemini(prompt)
if image_binary:
album = "nvsYwgq"
image_url = image_generator.upload_image_to_imgur(image_binary,album)
if image_url:
# 使用 push message 發送圖片,避免 reply token 超時
line_bot_api.push_message(
event.source.user_id,
[
TextSendMessage(text="✨ 這是我為你生成的圖片喔~"),
ImageSendMessage(original_content_url=image_url, preview_image_url=image_url)
]
)
else:
line_bot_api.push_message(
event.source.user_id,
TextSendMessage(text="⚠️ 圖片上傳失敗,請稍後再試~")
)
else:
line_bot_api.push_message(
event.source.user_id,
TextSendMessage(text="⚠️ 圖片生成失敗,請稍後再試~")
)
return
# ========
# 上傳圖片
# ========
if event.message.type == "image":
image_path = get_image_url(event.message.id)
if image_path:
store_user_message(user_id, "image", image_path)
line_bot_api.reply_message(event.reply_token, TextSendMessage(text="圖片已接收成功囉,幫我輸入你想詢問的問題喔~"))
else:
line_bot_api.reply_message(event.reply_token, TextSendMessage(text="沒有接收到圖片~"))
return
previous_message = get_previous_message(user_id)
if previous_message and previous_message["type"] == "image" and event.message.type == "text":
image_path = previous_message["content"]
user_text = event.message.text
store_user_message(user_id, "text", user_text)
try:
if not os.path.exists(image_path):
raise FileNotFoundError(f"圖片路徑無效:{image_path}")
organ = PIL.Image.open(image_path)
completion = chat.send_message([user_text, organ])
out = completion.text
except Exception as e:
out = f"發生錯誤: {e}"
# ========
# 純文字
# ========
else:
if event.message.type != "text":
line_bot_api.reply_message(event.reply_token, TextSendMessage(text="請輸入文字或圖片~"))
return
if event.message.text == "再見":
line_bot_api.reply_message(event.reply_token, TextSendMessage(text="Bye!"))
return
if working_status:
try:
prompt = event.message.text
store_user_message(user_id, "text", prompt)
completion = chat.send_message(prompt)
out = completion.text if completion.text else "我不太懂什麼意思也~"
except:
out = "執行出錯!請換個說法!"
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=out))
if __name__ == "__main__":
# 啟動 FastAPI 應用程式
uvicorn.run("main:app", host="0.0.0.0", port=7860, reload=True)
|