---
# System prepended metadata

title: Linebot 進階 - 小專案課程2
tags: [Linebot 專案課程]

---

# Linebot 進階 - 小專案課程2

:::warning
### 上一堂課
https://hackmd.io/@k0217/rJKNMyhDkx
:::
---
### 今日課程

* 目標：使用 Linebot 
    * 自動回覆（Line 官方帳號設定）
    * 網路搜尋（API）
    * 圖表（Python 套件）
    * Gemini 回覆（API）

* 示範案例：開發一個可以回應課表、查詢附近食物、股票以及使用 Gemini AI 去生成回應的 Line bot

* 技術：Line、Google API、Python 套件

---
## 第零步：設定今日課程（可參考上次課程）
使用以下圖片為圖文選單
![GDG-linebot](https://hackmd.io/_uploads/BkSHD5YFyx.png)
並依序點擊回應文字
* 課表
* 附近的餐廳
* 台積電股票

若是沒有產生回覆，可以至 render 的網站，點擊 「Deploy latest commit」，若是希望可以長期運轉不休眠，可以試試 `UptimeRobot`
![截圖 2025-02-12 上午11.59.21](https://hackmd.io/_uploads/HJwi3cYYJl.png)

:::spoiler **UptimeRobot 簡介**

#### 什麼是 UptimeRobot？
**UptimeRobot** 是一個網站監測工具，能定期檢查網站是否正常運行，並在網站當機時發送通知。它適合用來監控 API、伺服器或個人網站的可用性。

#### 主要功能
- **網站監測**：支援 HTTP(s)、Ping、Port（TCP）、Keyword 監測方式 
- **通知機制**：當網站無法訪問時，可透過 Email、Telegram、Discord、Slack、LINE 等方式通知 
- **免費方案**：每 5 分鐘檢測一次，最多監測 50 個網址 
- **付費方案**：更短的檢測間隔（最短 30 秒）及更多通知方式 

#### 使用方式
1. **註冊 UptimeRobot 帳號**：[UptimeRobot 官網](https://uptimerobot.com/) 
2. **新增監測**：輸入網站 URL，選擇監測類型與時間間隔 
3. **設定通知**：選擇 Email 或第三方工具接收異常通知 

#### 適用場景
- 監控個人網站、API、伺服器運行狀況 
- 保持免費伺服器（如 Vercel、Railway）存活 
- 提早發現網站掛掉問題，確保穩定運行 

:::

---
## 1. 自動回覆（使用課表舉例）
:::info
### 📌 自動回覆訊息 

**自動回覆訊息** 是 LINE Bot 內建的功能，能夠根據預設的條件回應使用者訊息，無需伺服器支援。自動回覆可設定為：

- **純文字回應**（如問候語、公告資訊）
- **圖片、影片、貼圖回應**（提供視覺化資訊）
- **按鈕選單回應**（讓使用者選擇進一步操作）

此功能適合用於 **基本客服、營運公告、常見問題回覆**，但無法處理動態內容或外部資料查詢。

---

### 📌 限制與注意事項 

1. **與 Webhook 互斥**：如果啟用 Webhook，LINE Developers 的 **自動回覆功能** 可能會出現錯誤。
2. **關鍵字設計需謹慎**：過於簡單的關鍵字可能導致誤觸，建議使用 **部分比對 + 關鍵字組合** 或 **正則表達式** 來提升準確度。
3. **免費方案訊息限制**：LINE 官方帳號的 **免費方案** 每月有訊息數量上限，超過後將無法回應。
4. **不適用於複雜邏輯**：若需要 **動態回應、外部 API 查詢、個人化內容**，應使用 Webhook 方式處理。

透過適當的 **關鍵字設計與回應設定**，可確保 LINE Bot 能夠有效提供資訊，提高使用者互動體驗。
:::
### 第一步：開啟「自動回覆」
進入 [Line Developers](https://developers.line.biz/zh-hant/) 並開啟自己的帳號![截圖 2025-02-12 上午11.30.06](https://hackmd.io/_uploads/rJeRBcKtJx.png)
點擊至 Messaging API，下滑至 LINE Official Account features
![截圖 2025-02-12 上午11.31.17](https://hackmd.io/_uploads/S1mML5YFyx.png)
點擊 Auto-reply messages 後面的 Edit
進到 Line official account manager 開啟「自動回應訊息」
![截圖 2025-02-12 上午11.34.04](https://hackmd.io/_uploads/rJdnIqFFke.png)


### 第二步：設定自動回覆
回到 Line Official Account Manager 首頁
點擊左側「自動回應訊息」
![截圖 2025-02-12 上午11.26.33](https://hackmd.io/_uploads/ryUxH9KKkx.png)

關閉原本的預設自動回覆
![截圖 2025-02-12 上午11.40.39](https://hackmd.io/_uploads/rJVB_5FtJe.png)

建立新回覆
![截圖 2025-02-12 上午11.42.00](https://hackmd.io/_uploads/BkEqd9YKJg.png)
「關鍵字回應」可依你的需求，選擇會觸發的關鍵字

下方可選擇回應類型，這裡先使用文字以及圖片
![截圖 2025-02-12 上午11.43.32](https://hackmd.io/_uploads/r1geF9Kt1g.png)

點擊建立後即可完成自動回覆
![截圖 2025-02-12 上午11.44.56](https://hackmd.io/_uploads/HkHBF5YKkg.png)

![Screenshot 2025-02-12 at 12.01.29 PM](https://hackmd.io/_uploads/HJeL65tYkl.jpg)

## 2. 網路搜尋（API）（以附近餐廳為例）
### 初始專案介紹
#### 檔案介紹：
:::spoiler 檔案介紹
將 github 的檔案下載至本地，並使用 VScode 打開
資料夾內容：
![截圖 2025-02-12 下午2.45.58](https://hackmd.io/_uploads/SythQaYK1x.png)
```
.env.example //環境變數範例
.gitignore //不上傳到 github 的檔案
app.py //主要的程式
README.md //專案說明
requirements.txt //需下載資源
```
要在本地用，需要依據 .env.example 檔，新增一個 .env 檔
:::
#### 初始程式碼介紹：
:::spoiler `app.py`介紹
#### 1. 環境變數與套件導入
```python=
import os
from dotenv import load_dotenv
from flask import Flask, request, abort
from linebot.v3.webhook import WebhookHandler, Event
from linebot.v3.exceptions import InvalidSignatureError
from linebot.v3.messaging.models import TextMessage
from linebot import LineBotApi, WebhookHandler
from linebot.models import (
    MessageEvent,
    TextMessage,
    TextSendMessage,
    ImageSendMessage)
from linebot.exceptions import InvalidSignatureError
import logging
```
    說明
    * os：用於讀取環境變數。
    * dotenv：load_dotenv() 可加載 .env 文件中的環境變數。
    * flask：導入 Flask 相關函式。
    * linebot.v3：LINE 官方 SDK，用於處理 LINE Bot 相關功能。
    * logging：設定應用的日誌級別。

---
#### 2. 環境變數設置
```python=
# 加載 .env 文件中的變數
load_dotenv()

# 從環境變數中讀取 LINE 的 Channel Access Token 和 Channel Secret
line_token = os.getenv('LINE_TOKEN')
line_secret = os.getenv('LINE_SECRET')

# 檢查是否設置了環境變數
if not line_token or not line_secret:
    print(f"LINE_TOKEN: {line_token}")  # 調試輸出
    print(f"LINE_SECRET: {line_secret}")  # 調試輸出
    raise ValueError("LINE_TOKEN 或 LINE_SECRET 未設置")
```
    說明
    * load_dotenv()：從 .env 文件讀取 LINE_TOKEN 和 LINE_SECRET。
---
#### 3. 初始化 LINE Bot API
```python=
line_bot_api = LineBotApi(line_token)
handler = WebhookHandler(line_secret)
```
    說明
    * LineBotApi：用於與 LINE 平台互動，如發送訊息。
    * WebhookHandler：用於處理 LINE 的 Webhook 事件。
---
#### 4. 建立 Flask 伺服器
```python=
app = Flask(__name__)
app.logger.setLevel(logging.DEBUG)
```
    說明
    * Flask(__name__)：初始化 Flask 應用。
    * 設置 logging.DEBUG 以顯示詳細日誌。
---
#### 5. 設置 Webhook
```python=
@app.route("/", methods=['POST'])
def callback():
    # 取得 X-Line-Signature 標頭
    signature = request.headers['X-Line-Signature']
    
    # 取得請求的原始內容
    body = request.get_data(as_text=True)
    app.logger.info(f"Request body: {body}")
    
    # 驗證簽名並處理請求
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    
    return 'OK'
```
    說明
    * @app.route("/", methods=['POST'])：建立 POST 請求的 Webhook。
    * request.headers['X-Line-Signature']：取得 LINE 傳來的簽名，用於驗證請求來源。
    * request.get_data(as_text=True)：取得請求的 JSON 內容。
    * handler.handle(body, signature)：處理 LINE 事件。
---
#### 6. 訊息事件處理
```python=
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event: Event):
    if event.message.type == "text":
        user_message = event.message.text  # 使用者的訊息
        app.logger.info(f"收到的訊息: {user_message}")
        
        reply_text = ("你說了：" + user_message)

        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=reply_text)
        )
```
    說明
    * @handler.add(MessageEvent, message=TextMessage)：監聽 TextMessage 事件。
    * event.message.text：取得使用者傳來的文字訊息。
    * line_bot_api.reply_message(event.reply_token, TextSendMessage(text=reply_text))：回覆使用者。
---
#### 7. 啟動 Flask 伺服器
```python=
if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)
```
    說明
    * if __name__ == "__main__"：確保程式是直接執行，而非作為模組導入。
    * app.run(host='0.0.0.0', port=5000)：啟動 Flask 伺服器，監聽所有 IP 地址的 5000 端口。
:::

---
### 使用 Google API 去找到附近餐廳（以台北101為例）
:::info
### 📌 前置知識點

#### 🔹 Google Places API 簡介
Google Places API 是 Google 提供的一個強大工具，能夠查詢 **附近的地點資訊**，例如：
- 餐廳
- 便利商店
- 觀光景點
- 公交站點

當我們希望透過 **LINE Bot 查詢附近餐廳**，可以使用 **Places API 的 `nearbysearch` 功能**，根據：
- **使用者的位置**（經緯度）
- **指定類別（如餐廳 `restaurant`）**
- **篩選條件（距離、評分等）**
來獲取附近的餐廳資訊。

#### 🔹 API 調用的基本流程（Python + `requests` 套件）
在 Python 中，我們可以透過 **`requests` 套件** 發送 HTTP 請求來獲取 Google Places API 的回應：
1. 先取得 **Google API Key**
2. 使用 `requests.get()` 呼叫 API
3. 解析回傳的 **JSON 資料**
4. 依據需要的條件進行篩選

#### 🔹 API 回傳的資料格式
Google Places API 會回傳一個 JSON 格式的清單，每個地點包含：
- name: 餐廳名稱
- rating: 評分
- user_ratings_total: 評價數量
- geometry.location.lat / geometry.location.lng: 經緯度
- vicinity: 地址
:::

### 第一步：申請 Google Cloud 專案
進入 [Google Cloud](https://cloud.google.com/?hl=zh-TW)，點擊右上角「控制台」，並新建專案
![截圖 2025-02-12 晚上9.56.01](https://hackmd.io/_uploads/HktatEcKyg.png)
點擊「API和服務」
![截圖 2025-02-12 晚上9.57.08](https://hackmd.io/_uploads/rkdatEcK1g.png)
查詢並啟用 Places API（這裡會需要輸入卡號，但只要不要亂按就不會收費）
![截圖 2025-02-12 晚上9.57.55](https://hackmd.io/_uploads/HyF6KN5F1x.png)
輸入完成後，紀錄你的 API KEY

- [ ] 簡報介紹 API

使用此 apikey 即可搜尋該位置（台北101）的附近餐廳
```
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=25.033964,121.564472&radius=1000&type=restaurant&key=你的API_KEY&language=zh-TW
```
:::info
可使用 postman 去測試
:::

### 第二步：修改 github 專案
1. 新增環境變數（在 render 新增一個 GOOGLE_PLACES_API_KEY 的環境變數，並放入剛剛的 APIKEY）
![截圖 2025-02-12 晚上11.28.01](https://hackmd.io/_uploads/ByifRNctkl.png)
2. 在專案中新增一個叫 `places.py` 的檔案，用來使用 api 去取用餐廳資訊
    ```python=
    import requests
    from dotenv import load_dotenv
    import os

    # 加載 .env 文件中的變數
    load_dotenv()

    # 你的 Google Places API Key
    API_KEY = os.getenv("GOOGLE_PLACES_API_KEY")

    def get_nearby_restaurants():
        """ 查詢附近的餐廳資訊 """
        latitude, longitude, radius = 25.033964, 121.564472, 1000  # 台北101
        url = (f"https://maps.googleapis.com/maps/api/place/nearbysearch/json"
               f"?location={latitude},{longitude}&radius={radius}&type=restaurant&key={API_KEY}&language=zh-TW")

        response = requests.get(url).json()
        results = []

        if "results" in response:
            for place in response["results"][:5]:
                name = place["name"]
                rating = place.get("rating", "N/A")
                address = place.get("vicinity", "未知地址")
                place_id = place["place_id"]
                map_url = f"https://www.google.com/maps/place/?q=place_id:{place_id}"
                results.append(f"🍽 {name} | ⭐ {rating}\n📍 {address}\n🔗 {map_url}")

        return "\n\n".join(results) if results else "找不到餐廳資訊 😢"

    ```
3. 在原本的 `app.py` 取用 `places.py` 的 function，用於 line 回覆
    * 最上方新增`from places import get_nearby_restaurants`
    * 將`reply_text = ("你說了：" + user_message)`修改為
        ```python=
        if user_message == "附近的餐廳":
            reply_text = get_nearby_restaurants()
        elif user_message == "課表":
            reply_text = "這是你的課表～"
        else:
            reply_text = ("你說了：" + user_message)
        ```
4. 將檔案推上 github
    
![LINE_capture_761067121.520449](https://hackmd.io/_uploads/HJLfJrqYJx.jpg)


## 3. 圖表(以台積電股票為例)

:::info 

### Python套件介紹
numpy：數值運算
matplotlib：繪製圖表
twstock：台灣股票資訊查詢
pandas：處理結構化數據
cloudinary：圖片與影片的雲端儲存與管理

:::

:::info
### 📌前置知識點（不需實作）
#### 🔹 1. 環境變數與 dotenv
在程式碼中，我們使用 `.env` 檔案來存放 **Cloudinary API 金鑰**，並透過 `dotenv` 套件讀取它。

##### `.env` 檔案格式
```=
CLOUDINARY_CLOUD_NAME=your_cloud_name 
CLOUDINARY_API_KEY=your_api_key 
CLOUDINARY_API_SECRET=your_api_secret
```
#### 📌 Python 讀取 `.env`
```python
import os
from dotenv import load_dotenv
load_dotenv()

cloud_name = os.getenv('CLOUDINARY_CLOUD_NAME')
api_key = os.getenv('CLOUDINARY_API_KEY')
api_secret = os.getenv('CLOUDINARY_API_SECRET')

```
🔹 應用場景：讓敏感資訊不直接寫在程式碼裡，提高安全性。

---
#### 🔹 2. 使用 twstock 取得台股資料
twstock 是 Python 的台股查詢套件，可獲取即時與歷史股價資訊。

#### 📌 基礎操作
```python=
import twstock

stock = twstock.Stock('2330')  # 查詢台積電
print(stock.price)  # 近期股價
print(stock.high)   # 每天最高價
print(stock.low)    # 每天最低價
print(stock.date)   # 日期
```
🔹 應用場景：可用於股票走勢分析、技術指標計算。

---
#### 🔹 3. 使用 pandas 轉換股票數據
pandas 是 Python 的數據處理套件，可以將 twstock 取得的數據轉成 DataFrame 格式，方便處理。
#### 📌 DataFrame 結構
```python=
import pandas as pd

stock_data = {
    'close': stock.close,
    'date': stock.date,
    'high': stock.high,
    'low': stock.low,
    'open': stock.open
}

df = pd.DataFrame.from_dict(stock_data)
print(df.head())  # 顯示前五筆數據
```
🔹 應用場景：DataFrame 讓我們可以輕鬆進行數據篩選、計算與視覺化。

---
#### 🔹 4. 使用 matplotlib 繪製股票走勢圖
matplotlib 是 Python 的視覺化工具，可用來繪製股價趨勢圖。

#### 📌 基本折線圖
```python=
import matplotlib.pyplot as plt

df.plot(x='date', y='close')
plt.title('2330 stock price')
plt.savefig('2330.png')
plt.close()

```
🔹 應用場景：視覺化股票價格變化，找出趨勢。

https://steam.oxxostudio.tw/category/python/example/matplotlib-index.html

---
#### 🔹 5. 使用 cloudinary 上傳圖片
因為 Line 傳輸圖片需要透過網址，但是在 python 這邊繪製的圖片沒有網址，所以需要上傳的雲端曲得網址後才可以使用 Line 傳輸。
cloudinary 允許我們將本地圖片上傳到雲端，並取得圖片網址。

#### 📌 設定 API
```python=
import cloudinary
import cloudinary.uploader

cloudinary.config(
    cloud_name=os.getenv('CLOUDINARY_CLOUD_NAME'),
    api_key=os.getenv('CLOUDINARY_API_KEY'),
    api_secret=os.getenv('CLOUDINARY_API_SECRET')
)

```
#### 📌 上傳圖片並獲取網址
```python=
def upload_to_cloudinary(file_path) -> str:
    """Upload an image to Cloudinary and return its URL."""
    try:
        response = cloudinary.uploader.upload(file_path)
        return response['secure_url']
    except Exception as e:
        print(f"Image upload failed: {e}")
        return None

```
🔹 應用場景：上傳股票趨勢圖，讓 LINE Bot 能回傳圖片網址。

:::
1. 加上需要的 Python 套件
在 requirements.txt 加入
    ```=
    numpy
    matplotlib
    twstock
    pandas
    cloudinary 
    ```

2. 新增環境變數（在 render 新增三個環境變數）（上傳繪製圖片）
    到 [Cloudinary](https://cloudinary.com/) 中申請 apikey
    登入後點擊 Coding with APIs and SDKs
    ![截圖 2025-02-13 中午12.10.13](https://hackmd.io/_uploads/BJQGbejtkx.png)
    點擊右下角 View API Keys
    ![截圖 2025-02-13 中午12.11.15](https://hackmd.io/_uploads/rJoZ-eiF1g.png) 
    記錄三個 APIKEY：Cloud name, API key, API secret
    並在 Render 中儲存環境變數
```
CLOUDINARY_API_KEY
CLOUDINARY_API_SECRET
CLOUDINARY_CLOUD_NAME
```
![截圖 2025-02-13 中午12.15.25](https://hackmd.io/_uploads/SkpJfgiK1l.png)

3. 修改程式碼
    新增`stock.py`檔案
    :::spoiler `stock.py`
    ```python=
    import os
    from dotenv import load_dotenv
    load_dotenv()
    import twstock
    import re
    import cloudinary
    import cloudinary.uploader
    import matplotlib
    matplotlib.use('Agg')  # For server compatibility
    import matplotlib.pyplot as plt
    import pandas as pd

    cloudinary.config(
        cloud_name=os.getenv('CLOUDINARY_CLOUD_NAME'),
        api_key=os.getenv('CLOUDINARY_API_KEY'),
        api_secret=os.getenv('CLOUDINARY_API_SECRET')
    )

    def upload_to_cloudinary(file_path) -> str:
        """Upload an image to Cloudinary and return its URL."""
        try:
            response = cloudinary.uploader.upload(file_path)
            return response['secure_url']
        except Exception as e:
            print(f"Image upload failed: {e}")
            return None

    def txt_to_img_url() -> str:
        try:
            sid = '2330'
            stock = twstock.Stock(sid)
            file_name = f'{sid}.png'

            # Prepare stock data for plotting
            stock_data = {
                'close': stock.close,
                'date': stock.date,
                'high': stock.high,
                'low': stock.low,
                'open': stock.open
            }
            df = pd.DataFrame.from_dict(stock_data)

                # Plot stock data
            df.plot(x='date', y='close')
            plt.title(f'{sid} stock price')
            plt.savefig(file_name)
            plt.close()

                # Upload the image to Cloudinary
            image_url = upload_to_cloudinary(file_name)

            if image_url:
                os.remove(file_name)
                return image_url
            else:
                return None

        except Exception as e:
            print(f"Error generating stock trend chart: {e}")
            return None
    ```
    :::

    在`app.py`中新增
    ```python=
    from stock import txt_to_img_url
    ```
    ```python=
    elif user_message == "台積電股票":
            try:
                image_url = txt_to_img_url()
                if not image_url:
                    error_message = f"抱歉，沒有取得股票趨勢圖，{image_url}。"
                    line_bot_api.reply_message(
                        event.reply_token,
                        TextMessage(text=error_message)
                    )
                    return
                line_bot_api.reply_message(
                    event.reply_token,
                    ImageSendMessage(
                        original_content_url=image_url,
                        preview_image_url=image_url
                    )
                )
            except Exception as e:
                error_message = f"抱歉，無法生成股票趨勢圖，錯誤原因：{e}"
                line_bot_api.reply_message(
                    event.reply_token,
                    TextMessage(text=error_message)
                )
            return
    ```
4. 將檔案推上 github
![IMG_E979438E6E2A-1](https://hackmd.io/_uploads/ryu6Exotye.jpg)


## 4. Gemini（AI 回覆訊息）
最後，將所有其他回覆交由 Gemini 處理
:::info
### 🤖 Gemini 回覆（Gemini API）
#### 🔹 1. 大語言模型（LLM）的基本概念
**大語言模型（LLM, Large Language Model）** 是基於深度學習的自然語言處理技術，能夠理解並生成類似人類的文字。

| 模型 | 提供者 | 特點 |
|------|------|------|
| **Gemini** | Google | 支援多模態（文字、圖片等），整合 Google 生態系 |
| **ChatGPT** | OpenAI | 通用 AI 對話助手，GPT-4 提供更強的推理能力 |
| **Claude** | Anthropic | 以安全性與對話長度優勢著稱 |

🔹 **應用場景**：Gemini 能夠回答問題、翻譯語言、生成文本等，非常適合用來提升 **LINE Bot 的互動性**。

---
### 🔹 2. 如何使用 Python 呼叫 Gemini API
Google 提供 `google.generativeai` 套件來簡化 API 呼叫。

#### 📌 安裝套件：
```bash
pip install google-generativeai
```
#### 📌 基本使用方式：
```python=
import google.generativeai as genai
import os

# 設定 API Key
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))

# 建立聊天模型
model = genai.GenerativeModel("gemini-pro")

# 發送請求
response = model.generate_content("介紹 Python 的特點")
print(response.text)

```
🔹 應用場景：Gemini API 可用於 智慧問答、內容生成，讓 LINE Bot 更有互動性。


:::
### 第一步：申請 Gemini API Key
1. 到 [Google AI Studio](https://aistudio.google.com/) 中申請
![截圖 2025-02-13 中午12.41.53](https://hackmd.io/_uploads/SyxQdgsFyg.png)

2. 點擊右上 Get API key
3. Create API key 並儲存

### 第二步：修改程式碼
1. 加上需要的 Python 套件
在 requirements.txt 加入 `google-generativeai
`
2. 新增環境變數（Gemini 的 APIKEY）
```
GEMINI_API_KEY
```
![截圖 2025-02-13 下午1.00.59](https://hackmd.io/_uploads/Byj52goKyx.png)

3. 修改 `app.py`
    加入（Gemini 的模型名可能改變，如果無法執行可以看 Gemini 官網查看可使用的模型名稱）
    ```python=
    import google.generativeai as genai
    ```
    ```python=
    genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
    model = genai.GenerativeModel("gemini-1.5-pro")
    ```
    將此程式碼刪除
    ```python=
    else:
        reply_text = ("你說了：" + user_message)
    ```
    修改成這樣
    ```python=
    else:
        response = model.generate_content(user_message) # 傳送使用者的問題給 Gemini
        reply_text = response.text if response else "抱歉，我無法回答這個問題。"
    ```
    
![IMG_4502D406165D-1](https://hackmd.io/_uploads/rJbaoxsK1e.jpg)

:::success
## 📝 補充知識

### 🔹 1. Token 限制與計費方式
Gemini API 採用 Token 機制計費，每次請求會消耗一定數量的 Token，因此需要考量 API 的使用成本。

#### 📌 Token 概念：
- 1 Token 約等於 **1 個英文單字或 1 個標點符號**
- **輸入 + 輸出** 都會消耗 Token
- **免費方案**：每日有 Token 限制
- **付費方案**：可額外購買 Token，但需要留意計費方式

---
### 🔹 2. 如何讓 LINE Bot 依據使用者問題選擇合適的回應？
當 LINE Bot 需要與 Gemini API 結合時，應該根據使用者的輸入決定 **是否使用 Gemini** 或 **其他 API**。

#### 📌 指令解析（Command Parsing）
可以讓使用者透過 **關鍵字** 或 **標籤** 來觸發不同功能。

| 指令 | 解析 | Bot 行為 |
|------|------|---------|
| `@股票 2330` | 股票查詢 | 呼叫 **twstock API** 查詢台積電股價 |
| `@天氣 台北` | 天氣查詢 | 呼叫 **Weather API** 獲取台北天氣 |
| `@AI Python 是什麼？` | 問答模式 | 呼叫 **Gemini API** 產生回應 |

🔹 **應用場景**：
- LINE Bot 需要 **指令解析**，確保 API 調用符合使用者需求
- 如果是 **一般對話**，則讓 Gemini 回答
- 如果是 **特定指令**（如股票、天氣），則調用對應的 API

---

### 🔹 3. 多回應模式（文字 / 圖片 / 語音）與 Gemini API 的擴展應用
Gemini API 除了純文字回應，還可以擴展至 **圖片辨識、語音輸出** 等多模態應用。

#### 📌 可能的擴展應用：
- **圖片理解**：讓 Gemini 分析圖片內容，回傳描述
- **語音輸出**：結合 Google TTS（文字轉語音），讓 AI 以語音回覆
- **多輪對話**：記住使用者上下文，進行更自然的交流

#### 📌 LINE Bot 回應類型：
| 模式 | 內容 | 技術 |
|------|------|------|
| 文字回應 | AI 生成的回覆 | Gemini API |
| 圖片回應 | 股票趨勢圖、AI 生成圖片 | Matplotlib / Cloudinary |
| 語音回應 | 朗讀 AI 回覆 | Google TTS API |

🔹 **應用場景**：
- **股票查詢** 可以回傳 **趨勢圖**
- **天氣查詢** 可以提供 **語音播報**
- **一般問答** 以 **純文字** 回覆，但可選擇擴展到 **語音模式**


:::


---

## 恭喜！完成這次的課程了🎉
若是沒跟上，這裡有完整程式碼
https://github.com/xujk0217/GDG_linebot_test/tree/course2

---
回饋問卷
https://tally.so/r/3lzadB

---
### 下一堂課：
https://hackmd.io/@kHwE-_lVR8W5i9sJMWakSg/Hy0ctEIylx