# 影片主題與成品概念 * 使用 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):用於自動接聽電話、收集資訊與轉接部門的智慧語音系統
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.