File size: 5,317 Bytes
55b1be9
075e34b
7d8cb48
2cf7795
 
 
76eaf5a
 
 
 
 
 
 
 
 
9accbde
 
ba5cd6b
9accbde
1ce0901
 
9accbde
1ce0901
f23a640
9accbde
55b1be9
351e467
9accbde
 
55b1be9
 
 
df5bf2a
55b1be9
 
 
 
9accbde
55b1be9
6482098
8d77e72
2cf7795
9accbde
6482098
34287b9
 
 
 
 
9accbde
0a52d39
3a2e91a
9accbde
34287b9
 
 
3a2e91a
9accbde
34287b9
0385c62
2cf7795
9accbde
4a7f8d2
3a2e91a
4a7f8d2
cdb7b92
9accbde
cdb7b92
9accbde
 
 
 
 
cdb7b92
9accbde
df7b5e5
9accbde
4a7f8d2
 
9accbde
 
3a2e91a
df7b5e5
9accbde
df7b5e5
 
9accbde
 
f493c1c
040e9ca
9accbde
6ec574f
9accbde
6ec574f
9accbde
 
 
df7b5e5
9accbde
 
df7b5e5
9accbde
4a7f8d2
 
619c607
3bf6983
 
9accbde
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ec574f
9accbde
 
 
 
 
 
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
from fastapi.middleware.cors import CORSMiddleware
from fastapi import FastAPI, Request,  Header, BackgroundTasks, HTTPException, status, staticfiles
from gradio_client import Client
import json
import os

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage, ImageSendMessage, AudioMessage
)

# 設定 GeminiRAG 的HF網址
client = Client(os.environ["GeminiRAGapi"], hf_token=os.environ['HF_TOKEN'])
# 設定 Line Bot 的 API 金鑰和秘密金鑰
line_bot_api = LineBotApi(os.environ["CHANNEL_ACCESS_TOKEN"])
line_handler = WebhookHandler(os.environ["CHANNEL_SECRET"])
# 設定是否正在與使用者交談
working_status = os.getenv("DEFALUT_TALKING", default = "true").lower() == "true"

# 建立 FastAPI 應用程式
app = FastAPI()
# app.mount("/static", staticfiles.StaticFiles(directory="static"), name="static")

# 設定 CORS,允許跨域請求
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 處理根路徑請求
@app.get("/")
def root():
    return {"title": "RAG 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"

# 處理文字訊息事件
@line_handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    global working_status
    
    # 檢查事件類型和訊息類型
    if event.type != "message" or event.message.type != "text":
        # 回覆錯誤訊息
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text="Event type error:[No message or the message does not contain text]")
        )
        
    # 檢查使用者是否輸入 "再見"
    elif event.message.text == "再見":
        # 回覆 "Bye!"
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text="Bye!")
        )
        return
       
    # 檢查是否正在與使用者交談
    elif working_status:
        try: 
            # 取得使用者輸入的文字
            prompt = event.message.text
            # 使用 GeminiRAGapi
            completion = client.predict(question=prompt, api_name="/predict")
            # 檢查生成結果是否為空
            if (completion != None):
                # 取得生成結果
                out = completion
            else:
                # 回覆 "Gemini沒答案!請換個說法!"
                out = "Gemini沒答案!請換個說法!"
        except:
            # 處理錯誤
            out = "Gemini執行出錯!請換個說法!" 
  
        # 回覆生成結果
        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)

# 註解說明:
# import 導入必要的套件
# line_bot_api 和 line_handler 設定 Line Bot API 和 webhook 處理器
# working_status 設定是否正在與使用者交談
# app 建立 FastAPI 應用程式
# app.add_middleware 設定 CORS
# @app.get("/") 處理根路徑請求
# @app.post("/webhook") 處理 Line Webhook 請求
# @line_handler.add(MessageEvent, message=TextMessage) 處理文字訊息事件
# if __name__ == "__main__": 啟動 FastAPI 應用程式
# 程式碼功能說明:
# 接著會建立 FastAPI 應用程式,並設定 CORS。
# 程式碼會定義兩個函數:
# root() 處理根路徑請求,返回一個簡單的 JSON 訊息。
# webhook() 處理 Line Webhook 請求,將處理 Line 事件的任務加入背景工作,並處理無效的簽章錯誤。
# 程式碼還定義一個函數 handle_message() 來處理文字訊息事件,它會檢查事件類型和訊息類型,並根據使用者輸入執行不同的動作:
# 如果使用者輸入 "再見",回覆 "Bye!"。
# 如果正在與使用者交談,則會使用 Gemini 模型生成文字,並將結果回覆給使用者。
# 最後,程式碼會啟動 FastAPI 應用程式,開始監聽 HTTP 請求。
# 程式碼運行方式:
# 將程式碼存為 main.py 文件。
# 在環境變數中設定 GeminiRAGapi, CHANNEL_ACCESS_TOKEN 和 CHANNEL_SECRET。
# 執行 uvicorn main:app --host 0.0.0.0 --port 7860 --reload 命令啟動 FastAPI 應用程式。
# 使用 Line 帳戶與 Line Bot 進行對話。
# 注意:
# 程式碼中使用os.environ["GeminiRAGapi"], os.environ["CHANNEL_ACCESS_TOKEN"] 和 os.environ["CHANNEL_SECRET"] 來存取環境變數,需要先在環境變數中設定這些值。
# 程式碼中使用 uvicorn 執行 FastAPI 應用程式,需要先安裝 uvicorn 套件。
# 程式碼中使用 linebot 套件,需要先安裝 linebot 套件。