# 影片主題與成品概念 * 使用 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
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up