# 影片主題與成品概念
* 使用 Python 打造具「代理(Agent)」能力的 AI 語音助理(Voice Assistant)
* 助理可呼叫資料庫、執行 Python 函數、接各種工具
* 範例情境:車廠客服中心(Auto Service Center)語音客服
* 第二階段示範:將後端語音助理整合到自訂前端網頁
# 範例情境:車廠語音客服流程

* 首頁是一個簡單 Landing Page,提供「Talk to an agent」按鈕
* 使用者輸入姓名後接入 AI 語音助理系統
* 助理會先請使用者提供車輛 VIN 或詢問是否建立新資料
* 若無資料:詢問車輛品牌、車型與年份,並建立新客戶/車輛 Profile
* 新資料會寫入資料庫,下次可憑 VIN 查詢車輛資訊
* 之後可依需求轉接到排程部門(例如預約保養、換機油)
# 專案重點能力
* AI Agent 具「工具(Tools)」能力,可:
* 讀寫資料庫(車輛與客戶資料)
* 根據用戶請求決定要呼叫哪個工具(例如建立 profile、查 VIN)
* 對話保持上下文,適合做客製客戶服務
* 使用者可延伸功能到其他情境,而不只車廠
# LiveKit 介紹與角色

* LiveKit 為開源、可免費使用的即時音/視訊與資料傳輸平台
* 被多家大公司使用,包括 OpenAI 的 Voice Mode 背後也使用 LiveKit
* 專長:超低延遲(ultra-low latency)的語音、影片、資料傳輸
* 可用於:即時 AI 語音助理、視訊會議、語音聊天室等
* 可使用官方雲端,也可自行架設 LiveKit Server
# LiveKit 專案與金鑰設定

* 到 cloud.livekit 網站註冊並登入帳號

* 建立新的 LiveKit Project(例如命名為 car service center)

* 進入 Settings → Keys,建立新 Key
* 取得並保存:
* WebSocket URL(LiveKit URL)
* API Key
* API Secret
* 用 .env 檔儲存上述資訊,供程式使用
# OpenAI API Key 設定

* 到 platform.openai.com 產生新的 API Key(例如命名 livekit car service)
* 可能需要綁定信用卡,但成本很低(幾分錢等級)
* 專案中使用 OpenAI 的 Realtime API,取得極低延遲回應
* 也可選擇其他模型供應商(如本地 AMA 等),但影片示範使用 OpenAI
# LiveKit 架構與資料流概念
* 使用者端(網頁、手機…)連到 LiveKit Cloud,建立一個 room
* 後端的「Agent 程式」也連入同一個 room,與使用者即時互動
* 所有音訊/文字透過 WebRTC 傳輸,由 LiveKit Cloud 負責協調
* Agent 再與 OpenAI Realtime API 溝通,取得語音/文字回應
* 可同時多 room、多 Agent,多人並行對話
* 開發者只需定義「Agent 行為與工具」,通訊細節由 LiveKit 處理

# .env 檔環境變數規劃
* livekit_url:存 LiveKit WebSocket URL
* livekit_api_key:存 LiveKit API Key
* livekit_api_secret:存 LiveKit API Secret
* openai_api_key:存 OpenAI API Key
* 名稱需與程式碼一致,讓 LiveKit SDK 可以自動讀取
# requirements.txt 依賴套件

* livekit-agents:LiveKit Agents SDK
* livekit-plugins-openai:LiveKit 與 OpenAI 的整合外掛
* livekit-plugins-solero:語音活動偵測(Voice Activity Detection)
* python-dotenv:載入 .env 環境變數
* livekit-api:後面用於產出 Token 等
* flask、flask-async、flask-cors、uvicorn:後面用於發 Token、串前端(授權與連線)
# 虛擬環境與依賴安裝流程

* 建立虛擬環境(Windows:python -m venv ai;Mac/Linux:python3 -m venv ai)
* 啟用虛擬環境:
* Windows(PowerShell):.\ai\Scripts\activate
* Mac/Linux:source ./ai/bin/activate
* 安裝依賴:pip install -r requirements.txt
* 目的:隔離專案套件,避免與系統或其他專案衝突
# 專案檔案結構

* agent.py:主入口,定義並啟動 AI 語音代理
* api.py:定義 Agent 可用的工具(functions),如資料庫操作等
* database_driver.py:負責資料庫連線與讀寫(車輛、客戶資料)
* prompts.py:放系統提示詞(system prompt)與歡迎語等字串
# agent.py:基本結構與 Import
* 匯入 LiveKit Agents 相關類別:AutoSubscribe、JobContext、WorkerOptions、CLI、LLM 等
* 匯入 MultimodalAgent:支援多模態(語音+文字等)
* 匯入 LiveKit OpenAI Plugin
* 匯入 dotenv 的 load_dotenv 及 os
* 呼叫 load_dotenv() 載入 .env 檔裡的環境變數
# agent.py:entrypoint 主流程
* 定義 async 函式 entrypoint(ctx: JobContext)
* await ctx.connect(auto_subscribe=AutoSubscribe.SUBSCRIBE_ALL),連線到 LiveKit 房間並訂閱所有 track(音訊、影像、文字)
* await ctx.wait_for_participant(),等待客戶端參與者加入房間
* 定義 OpenAI Realtime 模型:
* 設定 instructions(系統角色說明)
* 設定 voice(例如 Shimmer)
* 設定 temperature(例如 0.8)
* 設定 modalities(audio + text)
* 建立工具上下文(assistant function context),讓模型可呼叫自訂工具
* 以 MultimodalAgent 將 model 與 function context 組成一個 Agent
* agent.start(ctx.room),讓 Agent 加入該 LiveKit 房間開始互動
# api.py:工具類別雛型
* 匯入 LLM function context 類別
* 定義 class AssistantFnCtx(LLM.FunctionContext) 或類似名稱
* 在 **init** 中呼叫 super().**init**() 完成基底初始化
* 之後在此類別中新增方法(被當作 Tool),例如:
* 建立車輛 Profile
* 依 VIN 查詢車輛資訊
* 更新客戶資料
* 每個方法都會被模型視為可呼叫工具
# 透過 Multimodal Agent 綁定工具
* 在 agent.py 中匯入 AssistantFnCtx
* 建立 assistant = AssistantFnCtx()
* 建立 agent = MultimodalAgent(model=model, function_context=assistant)
* 這樣模型就具備呼叫 AssistantFnCtx 內工具方法的能力
# 對話啟動與歡迎訊息
* 取出 model.sessions[0] 作為當前 session
* 使用 session.conversation.item.create() 新增一個 ChatMessage:
* role 設為 assistant
* content 使用歡迎訊息(welcome_message)
* 呼叫 session.response.create(),根據這個訊息產生語音與文字回應
* 實際效果:Agent 一加入房間就會主動問候,並請使用者提供車輛 VIN 等資訊
# prompts.py:系統提示與歡迎文案
* instructions:描述助理角色,例如:
* 你是車廠 Call Center 的客服,需蒐集 VIN、車款、年份,並協助轉接部門等
* welcome_message:對使用者說的第一句話,例如:
* 歡迎來到 Auto Service Center,請提供車輛 VIN,若無資料可協助建立新檔案
* 這兩段文字可依自己專案情境自由修改
# 啟動 LiveKit Agent Worker
* 在 agent.py 結尾:
* if **name** == "**main**": CLI.run_app(WorkerOptions(entrypoint=entrypoint))
* 使用 CLI.run_app 啟動 LiveKit Agent Worker
* Worker 會讀取 .env 中的 LiveKit URL / API Key / Secret,自動接上 LiveKit Cloud
* 有客戶端加入房間時,Worker 會執行 entrypoint,創建並啟動 Agent
# 測試與 LiveKit Playground


* 執行:python agent.py dev(dev 模式)
* 確認無環境變數或拼字錯誤(例如 livekit_api_secret 名稱需正確)
* LiveKit 提供 Playground,可建立一個 Client 端加入房間測試語音互動
* 當 Client 連上房間,Agent 會自動加入並開始語音對話(如示範的車廠客服流程)
---
# 使用 LiveKit Agents Playground 測試語音代理
* 透過瀏覽器搜尋並開啟 LiveKit Agents Playground,選擇專案「car service center」後按 Connect 連線
* 首次連線時可能需要登入 LiveKit 帳號,之後可直接選專案並連上代理
* 代理啟動後會主動問候並請使用者提供車輛 VIN,或說出「建立新檔案」來建立個人檔案
* 若使用者沒有 VIN,代理會改為詢問姓名、電話與 Email,並建立新的使用者檔案
* 目前對話後半段的回應主要是模型自由發揮,尚未串接實際商業邏輯
* 若連線失敗,多半是環境變數或 API Key 設定錯誤,需要確認名稱與值是否填對
# 建立 SQLite 資料庫驅動(database driver)
* 使用 SQLite3 作為範例資料庫,實際可替換成 MongoDB、JSON 檔或記憶體資料庫等任意方案
* 透過 data class 定義車輛資料結構,欄位包含 VIN、make(車款)、model(型號)、year(年份)
* DatabaseDriver 類別在初始化時接收資料庫檔案路徑,並建立或開啟對應的 SQLite 檔案
* 初始化時會檢查是否已存在車輛資料表,若不存在則建立包含 VIN、make、model、year 欄位的資料表
* 透過 context manager 實作 get_connection,統一管理連線的開啟與關閉
# 車輛資料的新增與查詢操作
* create_car 函式負責將 VIN、make、model、year 插入資料庫並執行 commit
* create_car 成功後會回傳代表該車輛的物件,可供後續程式使用
* get_car_by_vin 依據 VIN 查詢資料庫,若無結果回傳 None,若有結果則回傳車輛物件
* 若需要更多操作(刪除、更新、多筆查詢)可以在此類別中自行擴充
# 在助手類別中導入資料庫與型別定義
* 在主程式中匯入 enum、typing.Annotated、logging 與剛剛建立的 DatabaseDriver 類別
* 建立 logger 物件並設定 log level,方便在終端機查看工具被呼叫的狀況與參數內容
* 建立 DatabaseDriver 實例並存成變數 DB,供後續工具函式直接存取資料庫
* 定義 car_details 的 Enum,列出 VIN、make、model、year 四個欄位名稱供程式集中管理
* 使用 Enum 讓欄位名稱更一致,方便在程式與模型之間對應正確欄位
# 儲存目前對話中關聯的車輛資訊
* 在助手類別內新增成員變數(例如 self._car_details),用於保存目前對話正在討論的車輛資訊
* 在初始化時將 VIN、make、model、year 欄位都設定為空字串,之後由工具填入實際值
* 以底線開頭命名代表此屬性是類別的內部狀態,不建議外部程式直接修改
* 利用這個狀態,代理可以在多輪對話中持續引用同一輛車,而不必每輪都重新詢問完整資訊
# 定義可供 LLM 呼叫的工具:查詢車與建立車輛
* 使用特定裝飾器(llm callable)將 Python 函式標記為「可被模型呼叫的工具」
* 為每個工具撰寫簡短的描述,說明功能與何時應該被呼叫,提供模型判斷依據
* lookup_car 工具會接收 VIN 字串,利用 Annotated 註明型別與說明文字讓模型知道如何填參數
* lookup_car 在執行時先用 logger 記錄收到的 VIN,接著呼叫 DB.get_car_by_vin 查詢資料庫
* 若查無資料則回傳「車輛未找到」之類訊息;若查到資料則更新 self._car_details 並組成可讀字串回傳
* create_car 工具接收 VIN、make、model、year 等參數,其中 year 使用 int 型別並同樣透過 Annotated 描述用途
* create_car 透過 DB.create_car 新增資料,失敗時回傳錯誤訊息,成功時更新 self._car_details 並回傳「車輛已建立」的文字
# 其他輔助方法:判斷是否已有車輛與取得車輛字串
* get_car_string 會將 self._car_details 中的所有欄位走訪一遍,組成多行字串便於輸出給模型
* has_car 回傳布林值,用來判斷目前 self._car_details 的 VIN 是否為空字串
* has_car 可用來決定代理要不要再次詢問 VIN 或需要先建立新車輛檔案
* get_car_details 也被註冊成 llm 工具,負責將目前車輛詳細資訊以字串形式回傳給模型
* get_car_details 呼叫 get_car_string 並寫入 log,方便確認工具何時被實際使用
# 在 Agents Playground 中驗證工具呼叫與 VIN 行為
* 重新啟動後端程式,回到 Agents Playground 按 Connect 連線並開啟對話
* 提供一組 VIN 時,代理會嘗試查詢資料庫,若找不到會提示是否要建立新車檔案
* 建立新車檔案時,代理會要求提供 make、model、year,並呼叫 create_car 將資料寫入資料庫
* 日誌中可以看到 logger 的輸出內容,驗證工具確實被呼叫與傳入參數的實際值
* 實測時發現模型對不合格式的 VIN 可能會自動補齊或產生其他 VIN,導致資料庫中的 VIN 與使用者說的不一致
* 目前示範先接受這種行為,之後可再加上 VIN 長度與格式檢查,避免儲存錯誤資料
* 下一步目標是依據「是否已經有 VIN/車輛檔案」來調整代理的提問邏輯,避免重複要使用者輸入相同資訊
---
# LiveKit 後端事件與對話分支邏輯

* 使用 `session.on(user_speech_uncommitted)` 事件,在使用者說完話時觸發回呼函式
* 回呼函式接收 `llm.ChatMessage` 型別的 `message` 作為輸入
* 將 `message.content` 統一轉成字串,方便後續處理
* 使用 `assistant_function.has_car` 狀態判斷使用者是否已經有車輛檔案
* 若已經有車輛檔案,則直接進入查詢處理流程(handle query)
* 若尚未有車輛檔案,則先進入車輛檔案查找或建立流程(find profile)
* 透過 state(是否有車輛資料)來決定對話樹往哪個分支繼續
# 訊息內容處理與影像過濾
* `message.content` 可能是字串或 list,需要先判斷型別
* 若是 list,會將其中多個元素組合成單一字串
* 在組合時,若元素是影像型別(例如 `llm.ChatImage`),用字串 `"image"` 取代
* 非影像元素則保留原本文字內容
* 各元素以換行字元 `\n` 連接成完整訊息字串
* 此步驟的目的是「去除影像資料,只保留可處理的文字內容」
# 查找/建立車輛檔案與查詢處理
* 定義 `find_profile(message: str)`,負責引導使用者提供或查找車輛資料
* 在 `find_profile` 中,透過 LLM system message 告訴模型要聚焦在「找出或建立車輛檔案」
* 定義 `handle_query(message: llm.ChatMessage)`,在已知車輛檔案情況下處理一般詢問
* 當 `has_car` 為真時,呼叫 `handle_query(message)`,直接處理使用者問題
* 當 `has_car` 為假時,呼叫 `find_profile(message)`,要求先提供 VIN 或車輛資訊
* 設計目的為:在完成車輛檔案建置以前,不進行轉接或其他部門處理
# VIN 查詢與 Prompt 設計
* 建立 `lookup_vin_message(message)` 函式,用來產生專門查 VIN 的 prompt 字串
* Prompt 指示 LLM:若使用者提供 VIN,先嘗試查詢資料庫
* 若沒有 VIN 或資料庫查無此 VIN,則建立新的車輛檔案
* 在後端使用 `lookup_vin_message(message)` 產生內容,作為 system prompt 傳給 LLM
* 這個 prompt 被用在「找車輛檔案 / 建立檔案」的那一支分支邏輯中
# 後端行為測試流程(對話範例)
* 啟動代理並連線到前端測試工具(agent playground)
* 系統先詢問:「請提供車輛 VIN 或是否要建立車輛檔案」
* 使用者提供 VIN `V12 345`,系統發現尚無此車輛檔案,詢問是否建立檔案
* 使用者提供車輛資訊「Jeep Wrangler 2021」,系統成功建立檔案
* 之後使用者詢問「能預約保養嗎」,系統即走到查詢分支回覆預約流程
* 再次斷線重連後,測試直接查詢同一 VIN,確認系統能從資料庫查回該車輛檔案
* 日誌中可看到 `user_data.create_car` 與 `user_data.lookup_car`,證明流程有依 VIN 正確寫入與查詢
# React 前端專案初始化與結構

* 將原本所有後端程式碼移到 `backend` 資料夾(包含虛擬環境)
* 刪除不必要的 `.pycache` 等暫存資料夾,整理專案結構
* 使用 `npm create vite@latest` 建立 `frontend` React 專案
* 建立專案時指定模板為 `react`
* 進入 `frontend` 資料夾後執行 `npm install` 安裝基本依賴
* 另外安裝 LiveKit 前端套件:`@livekit/components-react`、`@livekit/components-styles`、`livekit-client`
* 移除 React 專案預設的 `assets` 與 `public` 等不需要的資料夾
# 前端檔案與元件規劃
* 在 `src` 底下建立 `components` 資料夾
* 在 `components` 中建立 `LiveKitModal.jsx`,負責彈出視窗與 LiveKit room 連線
* 建立 `SimpleVoiceAssistant.jsx`,負責語音助理的 UI 與控制邏輯(之後使用)
* 建立 `SimpleVoiceAssistant.css`,存放語音助理相關樣式
* 在 `App.jsx` 中清除預設範例程式碼與 logo 匯入
* 在 `App.jsx` 中建立一個簡單首頁版面(header、搜尋列、CTA 按鈕等)
* 透過 `showSupport` state 控制是否顯示支援視窗(LiveKit modal)
# App 主畫面與支援按鈕行為
* 在 `App.jsx` 中使用 `useState(false)` 建立 `showSupport` 狀態
* 頁面包含一個 `header` 區塊,標示網站名稱(例如 AutoZone)
* `main` 區塊中有一個 hero 區段:標題「Get the right parts right now」、簡短說明文字
* hero 內有一個搜尋列,包含輸入框與搜尋按鈕,作為裝飾或之後擴充入口
* 頁面右下角有一個「Talk to an agent」按鈕,作為開啟語音助理的入口
* 點擊支援按鈕觸發 `handleSupportClick`,將 `showSupport` 設為 `true`
* 當 `showSupport` 為真時,在畫面上渲染 `<LiveKitModal setShowSupport={setShowSupport} />`
# LiveKitModal 結構與狀態
* 在 `LiveKitModal.jsx` 中匯入 `useState`、`useCallback`、`LiveKitRoom`、`RoomAudioRenderer` 與 LiveKit 樣式
* `LiveKitModal` 接收父層傳入的 `setShowSupport`,用來關閉 modal
* 使用 `isSubmittingName` state 控制目前是否在「輸入姓名」階段
* 使用 `name` state 存放使用者輸入的顯示名稱
* Modal 外層使用 `modal-overlay` 和 `modal-content` 之類的 class 來套用樣式
* 若 `isSubmittingName` 為 true,渲染一個表單要求使用者輸入姓名
* 表單包含文字輸入框、Connect 按鈕與 Cancel 按鈕
* Cancel 按鈕會呼叫 `setShowSupport(false)` 關閉 modal
* 連線完成後,會把 `isSubmittingName` 改成 false,改為顯示 LiveKitRoom
# LiveKitRoom 設定與連線行為
* 在 `LiveKitModal` 中使用 `<LiveKitRoom>` 元件作為與 LiveKit 伺服器的主要連線容器
* `serverUrl` 由環境變數讀取,之後會從 `.env` 設定
* `token` 屬性預留給之後的授權 Token(尚未實作)
* `connect` 設為 `true`,一旦元件被渲染就自動嘗試連線
* `video` 設為 `false`,暫時不使用視訊
* `audio` 設為 `true`,啟用音訊功能
* `onDisconnected` 事件中,呼叫 `setShowSupport(false)` 關閉 modal
* 在 `onDisconnected` 中也把 `isSubmittingName` 設回 `true`,下次開啟時重新要求姓名
* 在 `<LiveKitRoom>` 內部使用 `<RoomAudioRenderer>` 負責播放音訊
* 後續可在此區塊加入麥克風控制、輸入裝置選擇、波形視覺化、文字訊息顯示等元件
# 前端環境變數與 LiveKit URL 設定
* 在前端專案根目錄建立 `.env` 檔案
* 定義 `VITE_LIVEKIT_URL` 環境變數,用來存放 LiveKit 專案的 WSS 伺服器 URL
* 該 URL 需與後端使用的 LiveKit URL 一致,確保連線到同一個專案
* 在 `LiveKitModal.jsx` 中透過 `import.meta.env.VITE_LIVEKIT_URL` 讀取此變數
* 將 `serverUrl={import.meta.env.VITE_LIVEKIT_URL}` 傳給 `<LiveKitRoom>`
* Token 欄位保留,之後由後端產生授權 token 再注入前端使用
---
# LiveKit Access Token 概念與用途
* Token 是前端連到 LiveKit Room 的存取憑證,用來控制誰能連線
* 測試時可使用 LiveKit Cloud 產生的臨時 Token(約 15 分鐘 / 900 秒有效)
* 正式環境建議由後端伺服器動態產生 Token,並搭配使用者驗證
* Token 可限制可進入的房間,例如只允許加入 room B、不允許 room A
* 客戶端連線時必須攜帶 Token,LiveKit 依 Token 決定是否允許加入特定 Room
# 在 LiveKit Cloud 中產生臨時 Token
* 進入專案(例如 car service center),前往 Settings → Keys
* 選擇要使用的 Key,點擊「Generate token」產生臨時 Token
* Token 設定可包含使用者名稱、指定要進入的房間名稱
* 可勾選權限:是否能發佈音訊軌、訂閱軌、發送資料等
* 產生 Token 後將字串複製到前端程式中作為連線用 Token
# 前端 React:簡易 Voice Assistant 容器
* 在前端專案中建立 SimpleVoiceAssistant Component,作為語音助理 UI
* 匯入 LiveKit React 元件與 hooks:VoiceAssistant、BarVisualizer、VoiceAssistantControlBar、useTrackTranscription、useLocalParticipant 等
* 匯入 track 類型(自 livekit-client)、React 的 useEffect 與 useState、以及對應的 CSS 檔案
* Component 結構包含:外層 container、visualizer 區塊、control bar 區塊、conversation 區塊
* 在主頁(如 LiveKit Model 畫面)引入 SimpleVoiceAssistant 並渲染,搭配 RoomAudioRender 使用
# 連線與啟動 Agent 的流程
* 將 Token 寫入前端環境變數並在程式中讀取,用於建立 LiveKit 連線
* 首次測試時發現「能進入頁面,卻沒有任何語音互動」,原因是後端 Agent 尚未啟動
* 在後端資料夾啟用虛擬環境,執行例如 `python agent_dev.py` 以啟動 Agent
* 再次在前端點選「Talk to an agent」,填入名稱並連線,即可聽到 Agent 的語音回應
* 若修改了環境變數但前端未重新啟動,會造成 Token 未載入,需重啟前端開發伺服器
# 建立訊息顯示用的 Message 子元件
* 建立 Message Component,接收 props:type(agent 或 user)與 text(訊息內容)
* 使用 div 顯示一則訊息,包含發話者標籤與文字本體
* strong 文字作為前綴:type 為 agent 時顯示「Agent:」,否則顯示「You:」
* span 用於呈現實際的訊息文字,搭配 CSS class 區分樣式
* 需記得從 Component 回傳最外層 div,否則畫面不會顯示
# 從 Agent 與本機麥克風取得轉錄文字
* 使用 `useVoiceAssistant` 取得 Agent 的狀態、音訊 track 與 Agent 即時轉錄文字
* 使用 `useLocalParticipant` 取得本機參與者(使用者)的參與者物件及其麥克風 track
* 使用 `useTrackTranscription` 針對本機的麥克風 track 取得使用者的即時轉錄 segments
* 用 useState 建立 messages 狀態陣列,用於存放整理後的所有對話訊息
* 用 useEffect 監聽 agent transcriptions 與 user transcriptions 的變化,當有變化時重新整理 messages
# 整理並排序對話訊息
* 在 useEffect 中將 Agent 的 transcriptions 陣列 map 成含有 type: "agent" 的物件
* 將使用者的 transcriptions 陣列 map 成含有 type: "user" 的物件
* 合併兩者陣列後,依 first_received_time 排序,確保對話順序正確顯示
* 將排序後的陣列設定回 messages 狀態,用 messages.map 產生多個 Message 元件
* 在畫面中依序呈現 Agent 與使用者的對話內容
# 視覺化 Agent 音訊與控制條
* 在 visualizer 容器中使用 BarVisualizer 結合 Agent 的 audio track,顯示語音波形或音量條
* BarVisualizer 可調整 barCount 來改變顯示條的數量與寬度
* VoiceAssistantControlBar 提供預製控制 UI,包含連線、靜音等控制項
* UI 結構:上方或側邊顯示 audio visualizer,底部顯示控制列與對話訊息
# Token 過期(401)與錯誤排除
* 測試時出現 401 錯誤,原因為使用的 LiveKit Token 只有效 900 秒,已過期
* 需回到 LiveKit Cloud 的 Keys 頁面重新 Generate Token,再貼回前端程式
* 每次產生的新 Token 只適合短期測試,正式環境須改為後端動態簽發
* 若畫面可連線但無音訊或無訊息,多半與 Token 未載入、拼字錯誤或前端未重啟有關
# 修正程式小錯誤與最終狀態
* 一開始因變數命名錯誤(如 agent transcription vs agent transcriptions)導致轉錄無法顯示
* 修正 useEffect 依賴與 map 使用的變數名稱後,轉錄即能正確寫入 messages
* Message Component 遺漏 return 也會導致訊息不顯示,補上 return 後問題解決
* 修正這些錯誤後,前端能顯示語音波形、控制列與完整的雙向文字對話
* 至此簡易 Voice Assistant 前端已可正常運作,能與後端 Agent 進行語音互動並即時顯示文本
---
# 後端 Token 伺服器目的
* 前端不直接持有永久 Token,改由向自家後端請求一次性 Token
* 後端用 LiveKit API key / secret 代為簽發 Token
* 可控制誰能加入哪個房間、給什麼權限、如何管理房間
* 透過 `server.py` 建一個簡單 Flask API 來發 Token
# Flask 伺服器與 CORS
* 使用套件:flask、flask-cors、python-dotenv、livekit API、uuid、os
* `load_env` 載入環境變數(API key、API secret)
* `app = Flask(__name__)` 建立應用
* 用 `CORS(app, resources=...)` 放寬來源限制,避免前端呼叫時出現 CORS 錯誤
# Flask 啟動設定
* 在 `if __name__ == "__main__":` 中啟動伺服器
* `host="0.0.0.0"` 讓本機與其他裝置都能連線
* `port=50001` 提供給前端 Vite proxy 轉發
* `debug=True` 方便開發時看到錯誤與自動重啟
# 發 Token 的 API 端點
* 建立路由(例如 `/get_token`)處理前端請求
* 使用 GET 從 query string 讀取 `name`(使用者名稱)與 `room`(房間名稱,可選)
* 若未提供 `room`,後端自動產生新房間名稱
* 使用 LiveKit API 建立 access token,綁定:
* identity:用戶識別
* name:顯示名稱
* grants:允許加入該 room、roomJoin=true
* 回傳 `token.to_jwt()` 字串給前端
# 房間名稱生成與檢查
* 使用 `uuid.uuid4()` 產生隨機 id,取前幾碼加上前綴組成房名(例如 `room_xxxxxxxx`)
* 透過 LiveKit API 取得目前所有房間名稱清單
* 若新房名已存在,重新生成直到不重複為止
* 確保每次新對話預設在獨立房間中進行
# 取得現有房間列表
* 建立 LiveKit API client
* 呼叫 `room.list_rooms` 取得目前所有房間
* 從結果中抽出每個房間的名稱組成列表
* 使用完畢後呼叫非同步關閉方法(如 `await api.aclose()`)
* 提供給房名生成函式做「是否重複」檢查
# 後端整體流程
* 前端呼叫 `/get_token?name=XXX`(可選 `room=YYY`)
* 後端讀取 name、room,若沒 room 就產生新房名
* 使用 LiveKit API key / secret 簽出 access token
* Token grants 綁定指定 room 與權限
* 將 JWT token 字串回傳給前端
* 多個使用者同時按按鈕時,各拿到不同 room 的 token,互不干擾
# Vite Proxy 設定
* 在 Vite 設定檔中新增 server.proxy
* 將以 `/api` 開頭的請求代理到 `http://localhost:50001`
* 設定 `changeOrigin: true` 避免來源域名問題
* 使用 `rewrite` 把 `/api` 從路徑中移除,只保留實際後端路徑
* 讓前端用 `/api/get_token` 呼叫後端 `/get_token`,同時避開 CORS
# 前端取得 Token 的流程(LiveKitModal)
* 在 LiveKitModal 中建立 `token` 狀態儲存後端回傳的 JWT
* 使用 `useCallback` 定義 `getToken(name)` 非同步函式
* `getToken` 流程:
* 呼叫 `fetch("/api/get_token?name=...")`
* 使用 `encodeURIComponent` 編碼 name
* 以 `response.text()` 取得 token 字串
* 呼叫 `setToken(token)` 儲存 Token
* 將 `isSubmittingName` 設為 false 切換到 LiveKitRoom 畫面
* 發生錯誤時在 console 中輸出錯誤訊息
# 姓名送出與 LiveKitRoom 顯示條件
* 表單送出時的 handler:
* 接受事件 `e`,先 `e.preventDefault()` 阻止頁面重新整理
* 檢查 `name.trim()` 非空才呼叫 `getToken(name)`
* 畫面邏輯:
* `isSubmittingName` 為 true 時顯示輸入姓名表單
* `token` 存在時顯示 `<LiveKitRoom>`,並將 token 傳入
* 未取得 token 時不渲染 LiveKitRoom,以避免未授權錯誤
# 常見錯誤與修正
* 忘記在 submit handler 中接收 `e`,導致無法 `preventDefault` 而頁面刷新
* 忘記在 `useCallback` 裡補上依賴陣列,可能導致警告或不預期行為
* 後端關閉 LiveKit API client 使用錯誤方法,需改用非同步 `await api.aclose()`
* 若簽發流程或密鑰錯誤,LiveKit 會回傳 invalid authorization token,需要回頭檢查後端 Token 生成邏輯
# 獨立房間與延伸應用
* 每次按「talk to an agent」都會:
* 透過後端建立新房間名稱
* 發一組只能加入該房間的 Token 給前端
* 每位使用者都有獨立對話上下文與 AI agent 實例
* 若要做「多人同房間」或「真人客服加入」:
* 前端可指定同一 room 名稱給多個使用者
* 後端用不同 grants 設定不同權限(僅聽、可說、管理房間等)
---
# Terminology
* 語音助理代理(AI Voice Assistant Agent):具備聽說能力並可自動執行任務的智慧助理程式
* 代理能力(Agent Capabilities):AI 可主動呼叫工具、查資料庫、執行程式碼等的能力
* 函式呼叫(Function Calling):讓模型主動請求呼叫後端定義好的程式函式以完成具體操作的機制
* 資料庫互動(Database Interaction):代理透過程式碼連線資料庫,讀寫使用者或業務資料的過程
* 前後端整合(Frontend-Backend Integration):把瀏覽器介面與後端 AI 服務串接起來的實作方式
* 客製化前端(Custom Frontend):依照業務需求自行設計的網頁或應用介面,而非通用介面
* 試算示範頁(Landing Page Demo):用來展示功能與流程的簡化單頁網站範例
* 呼叫中心模擬(Call Center Simulation):用程式模擬電話客服流程的測試環境與範例
* 車輛服務中心(Auto Service Center):提供保養、維修與預約等服務的車廠或據點系統
* 車輛識別碼(VIN, Vehicle Identification Number):每台車唯一的識別碼,用來查詢車輛資料
* 客戶資料檔案(Customer Profile):在資料庫中儲存與客戶相關車輛與聯絡資訊的紀錄
* 預約排程(Service Appointment Scheduling):為客戶安排服務日期與時間的流程
* 部門轉接(Department Transfer):依需求將客戶導向不同部門或流程的路由邏輯
* 狀態導向對話(Stateful Conversation):對話會記住過去資訊並依目前狀態決定下一步的互動方式
* 業務流程自動化(Process Automation):用程式與 AI 取代重複、制式的人工流程
* LiveKit 平台(LiveKit):專門支援低延遲語音、視訊與即時資料傳輸的開源通訊框架
* 超低延遲傳輸(Ultra Low Latency):從說話到回應幾乎沒有感覺得到延遲的通訊特性
* WebRTC 通訊協定(WebRTC):瀏覽器與伺服器之間即時音訊與影像傳輸的標準技術
* 即時 AI 系統(Real-time AI System):輸入與輸出皆在極短時間內完成的 AI 應用
* 語音模式(Voice Mode):透過語音輸入與語音輸出與模型互動的工作模式
* 自架伺服器(Self-hosted Server):自行在自己的雲端或機房部署並維運服務的方式
* 雲端專案(Cloud Project):在雲端平台中建立的獨立環境,用來管理金鑰與資源
* API 金鑰(API Key):呼叫雲端服務時用來辨識與授權的機密字串
* WebSocket 位址(WebSocket URL):用於建立 WebSocket 連線的服務端網址
* 環境變數檔(.env File):集中存放 API 金鑰與設定的文字檔,不直接寫在程式碼中
* OpenAI 即時 API(OpenAI Realtime API):支援超低延遲雙向語音與文字互動的 OpenAI 介面
* 多代理並行(Multi-agent Concurrency):同一套後端同時服務多個房間或使用者的能力
* 房間會話(Room Session):LiveKit 中一個使用者與代理共用的即時通訊空間
* 開發需求檔(requirements.txt):列出專案所需 Python 套件與版本的設定檔
* 虛擬環境(Virtual Environment, venv):隔離不同專案套件與版本的 Python 執行環境
* LiveKit Agents 套件(livekit-agents):用來建立與管理 AI 代理的 LiveKit Python 工具包
* LiveKit OpenAI 外掛(livekit-plugins-openai):讓 LiveKit 代理可以直接串接 OpenAI 模型的外掛
* SolARo 聲音偵測外掛(livekit-plugins-solARo):用於偵測有無人說話的語音活動偵測外掛
* Flask 網頁框架(Flask):用來快速開發後端 API 與簡單網頁服務的 Python 框架
* CORS 支援(Flask-CORS):允許前端網域跨來源請求後端 API 的設定與套件
* Uvicorn 應用伺服器(Uvicorn):支援非同步執行、常搭配 FastAPI/Flask 的高效 Web 伺服器
* 授權權杖(Auth Token):前端連線到 LiveKit Cloud 時用來驗證身分的短期憑證
* Worker 選項(Worker Options):LiveKit 代理執行端的啟動與連線設定參數
* 入口函式(Entry Point):程式啟動時第一個被呼叫、負責初始化整個代理流程的函式
* 自動訂閱軌道(Auto Subscribe Tracks):自動訂閱房間內音訊、視訊與文字軌的設定
* 多模態代理(Multimodal Agent):可同時處理語音、文字,甚至影像等多種輸入輸出的代理
* 系統指示(System Instructions):告訴代理「應扮演誰、用什麼口吻與規則」的長規則文字
* 歡迎語提示(Welcome Message Prompt):在連線建立後,主動向使用者打招呼與提問的預設訊息
* 工具上下文(Function Context):集中宣告所有可供代理呼叫的工具與函式的類別或物件
* 對話項目(Conversation Item):在會話中代表單一輪訊息或事件的結構化單位
* 回應生成(Response Creation):依照目前對話內容與工具結果產生文字與語音輸出的過程
* 車輛資料庫驅動(Database Driver for Vehicles):專門處理車輛與客戶資料 CRUD 的程式模組
* 呼叫中心情境提示(Call Center Prompt):專門針對客服場景撰寫的系統指示與情境描述文字
* 語音體驗客製化(Voice Experience Customization):調整聲線、語氣、對話流程以符合品牌或服務需求的設計過程
* 智能代理(Intelligent Agent):可以自己判斷、回應使用者要求的程式
* 代理遊樂場(Agent Playground):用來測試和玩 AI 代理的線上介面
* LiveKit 專案(LiveKit Project):在 LiveKit 平台上建立的一個語音或視訊應用專案
* 前端介面(Frontend Interface):使用者在瀏覽器中看到並操作的畫面
* 測試環境(Testing Environment):專門用來試跑程式、不影響正式使用者的環境
* 登入憑證(Credentials):用來證明帳號身分的資料,例如帳號密碼或登入權杖
* 連線按鈕(Connect Button):按下後讓網頁和伺服器或代理建立連線的按鈕
* 對話代理(Conversational Agent):可以跟人用自然語言來回聊天的程式
* 業務邏輯(Business Logic):程式裡真正處理「要做什麼事」的規則和流程
* 環境變數(Environment Variable):放在系統裡的設定值,程式可以讀但不寫死在程式碼裡
* VIN 車身號碼(Vehicle Identification Number):每台車獨一無二的身分編號
* 使用者資料檔(User Profile):儲存使用者姓名、電話、Email 等資料的紀錄
* API 檔案(API File):裡面寫好對外提供功能的程式碼檔案
* 資料庫驅動程式(Database Driver):幫程式跟資料庫溝通的那層程式碼
* SQLite3 本地資料庫(SQLite3 Local Database):裝在同一台機器上的輕量級小型資料庫
* MongoDB 資料庫(MongoDB Database):一種用文件形式存資料的 NoSQL 資料庫
* JSON 檔資料庫(JSON File Database):用 JSON 檔案把資料存成一筆筆物件的方式
* 記憶體資料庫(In-memory Database):把資料放在記憶體裡,速度很快但關機就沒了
* 擴增式檢索生成(Retrieval Augmented Generation):先查資料再讓模型用資料來回答的方法
* 資料類別(DataClass):用來簡單定義一個資料結構的類別寫法
* 內容管理器(Context Manager):用 with 管理開啟和關閉資源的工具,例如資料庫連線
* 資料表(Database Table):在資料庫裡像 Excel 表格那樣的一張表
* 主鍵欄位(Primary Key):在資料表中用來唯一識別每一列的欄位
* 建立車輛紀錄(Create Car Record):在資料庫裡新增一台車的資料
* 依 VIN 查車(Get Car by VIN):用車身號碼去資料庫裡找對應的車輛資料
* 列舉型別(Enum Type):把一組固定選項定義成常數,避免亂填值
* 型別標註(Type Annotation):在程式碼裡寫出參數和回傳值應該是什麼型別
* 記錄器(Logger):負責把程式執行時的訊息印到終端機或檔案裡的工具
* 記錄等級(Logging Level):分級顯示訊息的重要程度,例如 info、error 等
* 偵錯輸出(Debug Output):幫助找錯時印出的詳細訊息
* 狀態上下文(Context State):程式目前記住的背景資料,例如目前在處理哪一台車
* 物件屬性(Object Attribute):屬於某個物件的變數,用來存該物件的資料
* 私有成員(Private Member):不希望被外部直接改動的屬性或方法,通常用底線開頭命名
* 工具函式(Tool Function):提供特定功能,給 AI 模型在需要時呼叫使用的函式
* 函式裝飾器(Function Decorator):用一行 @ 開頭的語法替函式加上額外功能
* 參數描述(Parameter Description):用文字說明這個參數是什麼、該放什麼內容
* 字串格式化(String Formatting):把變數插進字串裡,組成好讀的文字
* 鍵值迭代(Key-Value Iteration):一筆一筆走訪字典裡的鍵和對應的值
* 回傳訊息(Return Message):函式做完事後,回給呼叫者的一段文字結果
* 錯誤處理(Error Handling):當操作失敗時,回傳清楚的錯誤說明而不是讓程式當掉
* 工具呼叫(Tool Calling):AI 模型主動請程式幫忙執行某個功能並取得結果
* 車輛詳細資料(Car Details):關於車子的品牌、型號、年份、VIN 等資訊的集合
* 使用者設定檔(User Profile):系統裡為某個人建立的長期資料紀錄
* 資料驗證(Data Validation):在存資料之前先檢查內容是不是合理
* 唯一欄位(Unique Field):在資料表中不可以出現重複值的欄位
* 伺服器日誌(Server Logs):伺服器在背景記錄的所有執行訊息
* 函式重用(Function Reuse):同一段程式碼被多個地方重複使用,不用一直複製貼上
* 內部方法(Internal Method):只打算在類別內部使用,不給外部直接呼叫的方法
* 外部方法(Public Method):設計給外部程式呼叫使用的公開方法
* 行為控制(Behavior Control):依照目前狀態改變系統要問什麼或要做什麼
* 專案設定(Project Configuration):專案中各種重要參數和路徑的總設定
* 事件處理器(Event Handler):針對特定事件觸發、執行對應程式邏輯的函式
* 樹狀流程(Tree-like Flow):依照問題與回答逐步分支的對話與決策流程結構
* 對話流程設計(Conversation Flow Design):規劃語音助理依步驟提問與回應的整體腳本
* 使用者語音提交事件(User Speech Committed Event):偵測到使用者一句話說完並送出辨識結果的時間點事件
* Session.on 事件監聽(Session.on Event Listener):在 LiveKit 會話上註冊回呼以響應特定事件的機制
* LLM 聊天訊息(LLM Chat Message):以角色與內容封裝,送入或取出大語言模型的訊息物件
* 訊息內容正規化(Message Content Normalization):把清單、多段文字等轉成單一字串的整理步驟
* 多模態訊息(Multimodal Message):同時可能包含文字、影像、音訊等多種資料型態的訊息
* 影像訊息占位符(Image Placeholder):以文字標記替代實際影像內容,方便後續文字處理
* 系統狀態檢查(State Check):根據內部旗標判斷目前流程進展到哪個階段的動作
* 條件式分支(Conditional Branching):依 if/else 條件將程式導向不同處理路徑的控制結構
* 業務邏輯分支(Business Logic Branch):根據實際業務規則決定下一步要執行的流程分支
* 個人檔案查詢流程(Profile Lookup Flow):先確認是否已有客戶檔案,再決定建立或查詢的步驟
* 車輛狀態查詢(Vehicle State Query):對資料庫詢問特定車輛是否已存在或其詳細資訊的操作
* VIN 查詢邏輯(VIN Lookup Logic):依車輛識別碼搜尋對應車輛紀錄的程式規則
* 輔助函式(Helper Function):用來拆分重複邏輯、簡化主流程的輔助小函式
* 系統角色訊息(System Role Message):用來指示模型該扮演什麼角色與語氣的系統級提示字串
* 提示模板函式(Prompt Template Function):接收輸入訊息並產生完整提示詞字串的函式
* 動態提示生成(Dynamic Prompt Generation):根據使用者當前輸入即時組合出不同的提示內容
* 使用者查詢處理(User Query Handling):接收使用者問題後決定要回應、查庫或轉接的主邏輯
* 對話狀態管理(Conversation State Management):以變數或旗標記錄對話進度與已收集資訊的技術
* 資料庫建立車輛(Create Car in DB):在資料庫中新增一筆車輛與其 VIN 等相關資料的操作
* 使用者資料日誌(User Data Logs):記錄每次建立或查詢客戶資料的後端 Log
* 後端日誌檢查(Backend Log Inspection):開發者透過伺服器 Log 追蹤與除錯流程的行為
* 會話重置測試(Session Reset Testing):斷線重連、模擬新對話來驗證狀態初始化是否正確
* 重新連線測試(Reconnect Testing):中斷連線後再加入房間確認代理是否能重新工作
* 非有效 VIN 處理(Invalid VIN Handling):對不合格式或不存在的車輛識別碼給出適當反應的邏輯
* 提示詞強化(Prompt Refinement):針對模型行為調整與補充提示內容以改善結果
* AI 捷徑行為(Heuristic Shortcut Behavior):模型憑經驗「猜測」結果而非完全遵照指示的現象
* 嚴格匹配條件(Strict Match Condition):要求模型精確遵守特定字串或格式的匹配規則
* 函式級權責分離(Function Responsibility Separation):將不同任務分拆到不同函式中以降低耦合度
* 後端程式整理(Backend Code Refactoring):調整檔案與程式結構以提升可讀性與維護性
* 資料夾結構調整(Folder Structure Organization):將前端、後端、共用模組等分開管理的做法
* 前後端分離(Frontend-Backend Separation):將 UI 與伺服器邏輯獨立成不同專案或服務的架構模式
* React 前端框架(React Framework):以元件化方式打造互動式網頁介面的 JavaScript 函式庫
* Vite 專案腳手架(Vite Scaffolding):用 Vite 快速產生並啟動前端開發環境的流程
* NPM 套件管理器(NPM Package Manager):用來安裝與管理 JavaScript 套件的工具
* LiveKit React 元件(LiveKit React Components):封裝好房間、音訊與參與者 UI 的 React 元件集合
* LiveKit Client SDK(LiveKit Client SDK):前端連線 LiveKit 房間、處理 WebRTC 的開發工具包
* CSS 樣式表(CSS Stylesheet):定義網頁排版、顏色與動畫效果的樣式檔案
* React 元件拆分(Component Decomposition):將頁面拆成多個小元件以便重用與維護的作法
* 狀態鉤子 useState(useState Hook):在 React 函式元件中管理本地狀態的官方 Hook
* 支援視窗(Support Modal):以浮動視窗方式顯示客服或語音助理入口的 UI 元件
* 表單提交事件(Form Submit Event):使用者送出表單時觸發、用來處理輸入資料的事件
* 受控輸入欄位(Controlled Input Field):由 React 狀態完全控制內容的輸入元件模式
* LiveKit Room 元件(LiveKit Room Component):負責建立與管理與 LiveKit 房間連線的 React 元件
* 房間音訊渲染器(Room Audio Renderer):將 WebRTC 音訊串流播放給使用者聽的 LiveKit 元件
* 斷線回呼(OnDisconnected Callback):在使用者離開房間時被呼叫,用來清理狀態的函式
* 伺服器 URL 環境變數(Server URL Environment Variable):以環境變數方式存放 LiveKit 伺服器位址的設定
* 授權權杖(Auth Token):前端連線 LiveKit 房間時用來驗證與授權的短期憑證
* 訪問權杖(Access Token):讓使用者有權連到指定房間的「通行證」字串
* 存取憑證(Access Credentials):證明你有權使用服務的一組資料,像帳號身分證明
* 房間識別碼(Room ID):用來分辨不同語音房間的代號
* LiveKit 專案(LiveKit Project):在 LiveKit 平台上建立的一個應用程式專案
* 臨時權杖(Temporary Token):只能用短時間的權杖,用來做測試用
* 生產環境(Production Environment):真正給一般使用者使用的正式系統環境
* 後端伺服器(Backend Server):在後面處理資料、發權杖、管權限的程式與機器
* 使用者驗證(User Authentication):確認使用者是不是真的是他說的那個人的過程
* 前端應用程式(Frontend Application):跑在瀏覽器裡、讓使用者看到和操作的程式
* LiveKit Cloud 設定(LiveKit Cloud Settings):在 LiveKit 後台調整金鑰、權限等的設定頁面
* API 金鑰(API Key):用來呼叫雲端服務的秘密字串,代表你的身分
* 權杖產生(Token Generation):在伺服器上建立一個新的存取權杖的動作
* 使用者名稱(Username):代表使用者身分的一段名字或代號
* 參與權限(Participate Permission):允許使用者加入房間並當成參與者的權限
* 發佈軌道權限(Publish Tracks Permission):允許使用者把自己的音訊或視訊送進房間的權限
* 訂閱軌道權限(Subscribe Tracks Permission):允許使用者收聽或觀看房間裡其他人軌道的權限
* 發佈資料權限(Publish Data Permission):允許使用者送文字或訊號資料到房間內的權限
* React 元件(React Component):React 裡可重複使用的一小塊畫面或功能
* Voice Assistant 元件(Voice Assistant Component):專門顯示語音助理畫面與對話的 React 元件
* Bar Visualizer(Bar Visualizer):用一條條柱狀線動來動去顯示聲音強弱的畫面元件
* 控制列元件(Control Bar Component):提供開始、停止、靜音等控制按鈕的一條工具列
* 轉錄鉤子(Transcription Hook):專門用來取得文字轉錄結果的 React Hook
* useVoiceAssistant 鉤子(useVoiceAssistant Hook):幫你拿到語音助理狀態與音訊軌的 Hook
* useTrackTranscription 鉤子(useTrackTranscription Hook):用來讀取某條音訊軌文字轉錄內容的 Hook
* useLocalParticipant 鉤子(useLocalParticipant Hook):取得目前「自己」這個參與者資訊的 Hook
* useState 狀態鉤子(useState Hook):在 React 裡用來記住和更新畫面狀態的工具
* useEffect 副作用鉤子(useEffect Hook):在資料變化時執行額外程式碼的工具
* LiveKit 客戶端(LiveKit Client):在前端負責跟 LiveKit 伺服器通訊的程式庫
* 音訊軌道(Audio Track):代表一條聲音來源的資料線,例如麥克風聲音
* 參與者物件(Participant Object):存放某個使用者在房間裡的狀態與軌道資訊的物件
* CSS 樣式檔(CSS Stylesheet):控制網頁顏色、大小、排版的設定檔案
* 容器區塊(Container Div):用來包住整個元件內容的外層區塊
* 視覺化區塊(Visualizer Section):專門放聲音可視化畫面的畫面區域
* 對話區塊(Conversation Section):用來顯示人和語音助理對話文字的畫面區域
* 訊息元件(Message Component):負責顯示單一句對話內容的小元件
* 訊息類型(Message Type):用來區分這句話是「代理」說的還是「你」說的標記
* 轉錄片段(Transcription Segment):一小段被系統切出來的句子或片語文字
* 訊息排序(Message Sorting):按照時間先後把所有對話排好順序的動作
* 接收時間戳記(First Received Time):這句話第一次被系統收到的時間記錄
* 陣列合併運算子(Spread Operator):用「...」把多個陣列或物件展開再合併的語法
* 陣列映射函式(Array Map Function):對陣列每一項做處理後,產生新陣列的函式
* 陣列排序函式(Array Sort Function):按照一定規則把陣列元素重新排順序的函式
* Key 屬性(Key Prop):在 React 中幫每個列表項目加上唯一識別用的屬性
* 401 未授權錯誤(401 Unauthorized Error):代表沒有正確身分或權杖無效的網路錯誤碼
* 環境變數檔(Environment Variable File):存放 API 金鑰、URL 等敏感設定的檔案
* 前端開發伺服器(Frontend Dev Server):在本機跑起來,用來開發與預覽前端程式的伺服器
* 虛擬環境啟動(Virtual Environment Activation):在專案中打開專用 Python 環境的步驟
* 日誌輸出(Log Output):程式在背景印出來,用來除錯與觀察行為的文字訊息
* 代理連線(Agent Connection):語音代理成功加入同一個 LiveKit 房間的狀態
* 語音助理介面(Voice Assistant Interface):使用者與語音代理互動時看到的整體畫面與控制區域
* 權杖簽發伺服器(Token Issuing Server):專門負責產生並回傳存取權杖給前端或客戶端的後端服務
* 存取權杖(Access Token):用來授權用戶連線到特定房間或資源的短期憑證
* JSON 網頁權杖(JSON Web Token, JWT):以 JSON 格式封裝身分與授權資訊的可簽名權杖標準
* 授權伺服器(Authorization Server):負責驗證身分並決定是否簽發權杖的伺服器角色
* LiveKit 視訊 API(LiveKit Video API):LiveKit 提供用於管理房間、參與者與權杖的後端介面
* 房間識別碼(Room Identifier):用來區分不同 LiveKit 房間實例的唯一名稱或 ID
* 參與者身分(Participant Identity):在房間中代表使用者或代理的唯一身分標記
* 房間清單查詢(List Rooms Request):向 LiveKit 要求目前所有活躍房間資訊的 API 呼叫
* 多房間並發(Room Concurrency):同一套系統同時支援多個獨立房間運作的能力
* 通用唯一識別碼(UUID, Universally Unique Identifier):以亂數或時間生成、高機率不重複的識別字串
* Flask 網頁框架(Flask Web Framework):用來快速建立 HTTP API 與後端服務的輕量級 Python 框架
* Flask 路由(Flask Route):對應特定 URL 路徑並處理請求的後端函式設定
* 查詢參數(Query Parameter):位於 URL 問號後、以 key=value 形式傳遞的請求參數
* 跨來源資源共用(CORS, Cross-Origin Resource Sharing):允許不同網域之間存取資源的瀏覽器安全機制
* 相同來源政策(Same-origin Policy):限制網頁只可存取同一網域資源的瀏覽器安全規則
* CORS 中介層(CORS Middleware):在後端統一設定允許來源與 HTTP 標頭的處理元件
* 反向代理設定(Reverse Proxy Configuration):在前端開發伺服器中轉發 API 請求到後端的設定方式
* 路徑改寫(Path Rewrite):在代理過程中修改請求 URL 路徑以符合後端實際端點的技巧
* Vite 開發伺服器(Vite Dev Server):提供熱更新與 Proxy 功能的前端本機開發環境
* 前後端分離架構(Separated Frontend-Backend Architecture):將 UI 與 API 伺服器獨立部署與維護的系統設計
* 非同步函式(Async Function):可搭配 await、在等待 I/O 時不阻塞執行緒的函式
* await 關鍵字(await Keyword):在非同步函式中暫停直到協程或 Promise 完成的語法
* 虛擬環境(Virtual Environment, venv):隔離不同專案依賴套件與版本的 Python 執行環境
* LiveKit 存取權杖類別(LiveKit AccessToken Class):用來組裝身分、授權與房間資訊並輸出 JWT 的類別
* 視訊授權設定(Video Grants):指定使用者在 LiveKit 視訊服務中可執行操作的權限集合
* 房間加入權限(Room Join Grant):控制使用者是否有權加入指定房間的授權旗標
* WebSocket 伺服器網址(WebSocket URL):建立即時雙向通訊連線時使用的 WSS/WS 端點位址
* API 金鑰(API Key):識別應用程式來源、用於呼叫後端服務的公開憑證
* API 密鑰(API Secret):與 API 金鑰搭配、用於簽名與驗證請求真實性的私密字串
* 名稱碰撞(Name Collision):隨機生成的房間或資源名稱不小心與現有名稱重複的情況
* 唯一房間名稱生成(Unique Room Name Generation):透過亂數與檢查避免房間名稱重複的演算法
* 後端日誌紀錄(Backend Logging):在伺服器紀錄請求、錯誤與狀態變化以便除錯的做法
* HTTP GET 請求(HTTP GET Request):用於向伺服器索取資料、不應修改狀態的 HTTP 方法
* Fetch API(Fetch API):瀏覽器端用來發送 HTTP 請求並處理回應的標準 JavaScript 介面
* URL 編碼(URL Encoding):將特殊字元轉換為安全的百分比編碼以放入網址的處理方式
* 例外處理機制(Exception Handling):在程式運行錯誤時捕捉並妥善處理的錯誤控制流程
* 除錯模式(Debug Mode):在開發中提供詳細錯誤訊息與自動重啟的伺服器運行模式
* 本機開發環境(Local Development Environment):在自己電腦上同時啟動前端與後端的測試環境
* 多房間會話管理(Multi-Room Session Management):在後端同時追蹤、建立與銷毀多個房間會話的能力
* 語音助理前端整合(Voice Assistant Frontend Integration):在網頁 UI 中嵌入並控制語音代理的整合方式
* 授權權限設計(Authorization Grant Design):規劃權杖中可執行動作與資源存取範圍的設計工作
* WebRTC 媒體會話(WebRTC Media Session):透過瀏覽器點對點傳輸音訊與視訊的即時通訊流程
* 雙向串流語音互動(Bidirectional Streaming Voice Interaction):使用者與代理雙向持續傳送與接收語音資料的互動模式
* 身分驗證與授權(Authentication and Authorization):先確認是誰,再決定可做什麼的安全機制組合
* 後端 API 代理設定(Backend API Proxy Configuration):在前端開發工具中設定 API 轉發路由到後端的細節
* 端點安全性(Endpoint Security):保護 API 路徑不被未授權或惡意存取的安全措施
* 連線位址設定(Connection URL Configuration):在前端或後端指定要連線之伺服器 URL 的設定
* 環境變數載入(Environment Variable Loading):在程式啟動時讀取 .env 或系統變數作為設定來源的過程
* 房間生命週期管理(Room Lifecycle Management):從房間建立、使用到關閉整個過程的管理策略
* 多使用者隔離會話(Isolated User Sessions):讓每位使用者擁有獨立房間與對話上下文、互不干擾的設計
* 呼叫中心語音代理(Call Center Voice Agent):用於自動接聽電話、收集資訊與轉接部門的智慧語音系統