本文為 聊天機器人-建議回復 系列文,第 10 篇:
- 如何用「建議回覆」提升 AI 客服體驗?讓對話更快更準確!
- 如何設計高效的快速回復 (Quick Replies) 功能?—— 完整指南
- 如何取得 OpenAI 的 API 金鑰:詳細步驟與完整指南
- 使用 Python-dotenv 管理環境變數:完整指南
- OpenAI 套件介紹(Python)—— 從安裝到實戰應用
- 設計高效 Prompt 工程:提升 AI 生成 Quick Replies 的準確性
- 實作 Quick Replies 生成函式:完整指南
- 結構化數據整合與上下文處理:提升 AI 生成 Quick Replies 的準確性
- 生成回覆與異常處理:確保 AI 提供高效、可靠的建議回覆
- 自動化測試與效能監控:確保 Quick Replies 生成穩定可靠 👈進度
- 優化策略與擴展應用:提升 AI 建議回覆(Quick Replies)的效能與適應性
在 AI 驅動的聊天機器人中,「建議回覆 (Quick Replies)」 是提升用戶體驗的重要功能。
然而,如果這個功能在生成時出現異常、回應延遲,甚至產生錯誤內容,可能會影響用戶體驗,甚至降低信任度。
因此,我們需要建立一套自動化測試與效能監控機制,確保 Quick Replies 在各種情境下都能穩定運行。
本篇文章將介紹如何設計自動化測試來驗證 Quick Replies 的正確性,並透過效能監控來評估 AI 生成的速度與穩定性。
我們將透過 Python 測試框架與效能分析工具,建立一個完整的測試流程,確保 Quick Replies 在實際應用中不會出現意外狀況。
自動化測試的目標
自動化測試的核心目標是確保 Quick Replies 的輸出符合預期,包括:
- 格式正確性:確保回應為 JSON 陣列,且包含預定數量的 Quick Replies。
- 內容準確性:驗證生成的 Quick Replies 是否符合輸入的對話歷史、FAQ、產品清單等數據。
- 錯誤處理能力:測試異常情境,如 API 超時、無效輸入等,以確保系統能夠妥善應對。
- 效能監控:追蹤 AI 回應的時間,分析平均回應速度與可能的瓶頸。
設計自動化測試腳本
在 test_quick_replies.py 中,我們實作了一個測試腳本,針對 Quick Replies 進行大量測試,並記錄測試結果。
測試邏輯
該測試腳本會執行以下步驟:
- 載入測試數據(包含
chat_history、faq_list、product_list)。 - 執行 50 次測試(可根據需求調整),記錄回應時間與輸出結果。
- 驗證 JSON 格式與 Quick Replies 數量,確保符合預期。
- 記錄成功與失敗的測試結果,並計算效能指標(平均回應時間、成功率等)。
- 輸出測試結果至
test_results.json,方便進一步分析。
核心程式碼解析
import json
import time
from generate_quick_replies import generate_quick_replies
from test_data import chat_history, faq_list, product_list
# 測試參數
TEST_RUNS = 50 # 測試次數
success_count = 0
fail_count = 0
response_times = []
test_results = []
# 進行測試
for i in range(TEST_RUNS):
start_time = time.time()
try:
replies = generate_quick_replies(chat_history, faq_list, product_list)
end_time = time.time()
response_time = round(end_time - start_time, 2)
# 驗證輸出格式
assert isinstance(replies, list), "輸出格式錯誤,應該為 JSON 陣列"
assert len(replies) == 5, f"輸出數量錯誤,應該是 5 個,但收到 {len(replies)} 個"
success_count += 1
response_times.append(response_time)
test_results.append({"test_case": i+1, "response_time": response_time, "quick_replies": replies})
except Exception as e:
fail_count += 1
test_results.append({"test_case": i+1, "error": str(e)})
# 計算效能指標
summary = {
"total_tests": TEST_RUNS,
"success_count": success_count,
"fail_count": fail_count,
"avg_response_time": round(sum(response_times) / len(response_times), 2) if response_times else None,
"min_response_time": min(response_times) if response_times else None,
"max_response_time": max(response_times) if response_times else None
}
# 儲存結果
final_data = {"summary": summary, "tests": test_results}
with open("test_results.json", "w", encoding="utf-8") as f:
json.dump(final_data, f, ensure_ascii=False, indent=4)
print("✅ 測試完成,結果已儲存至 test_results.json")
測試結果解讀
測試完成後,系統會輸出 test_results.json,其中包含:
- 總測試次數
- 成功與失敗測試數
- 平均回應時間 (
avg_response_time) - 最快與最慢回應時間
- 每個測試案例的回應內容
代碼解析
引入必要的模組
import json
import time
from generate_quick_replies import generate_quick_replies
from test_data import chat_history, faq_list, product_list
功能解析
json:用於讀寫 JSON 檔案(儲存測試結果)。time:用來計算 AI 生成 Quick Replies 所需的時間(效能監控)。generate_quick_replies:從generate_quick_replies.py匯入核心函數,負責根據對話歷史 (chat_history)、FAQ (faq_list)、產品列表 (product_list) 產生建議回覆。test_data.py:包含測試用的輸入數據,如chat_history(過往聊天記錄)、faq_list(常見問題)、product_list(商品資訊)。
設定測試參數
TEST_RUNS = 50 # 測試次數
success_count = 0
fail_count = 0
response_times = []
test_results = []
變數解析
TEST_RUNS = 50:測試的迴圈次數,表示這段程式碼會重複測試 50 次。success_count = 0:紀錄成功測試的次數。fail_count = 0:紀錄失敗測試的次數。response_times = []:存儲每次 AI 生成 Quick Replies 所花費的時間,用於計算效能指標(平均回應時間、最短與最長回應時間)。test_results = []:存放每次測試的詳細結果(包含回應內容與執行時間)。
進行測試(迴圈測試 50 次)
for i in range(TEST_RUNS):
start_time = time.time()
try:
replies = generate_quick_replies(chat_history, faq_list, product_list)
end_time = time.time()
response_time = round(end_time - start_time, 2)
功能解析
for i in range(TEST_RUNS): 迴圈 50 次,每次測試一次generate_quick_replies函式。start_time = time.time():記錄請求發送的時間點(測試開始)。generate_quick_replies(chat_history, faq_list, product_list):- 調用核心函式
generate_quick_replies,根據提供的chat_history、faq_list和product_list產生建議回覆。
- 調用核心函式
end_time = time.time():記錄請求完成的時間點(測試結束)。response_time = round(end_time - start_time, 2):- 計算回應時間,單位為秒,並四捨五入到小數點後兩位。
驗證回應內容
# 驗證輸出格式
assert isinstance(replies, list), "輸出格式錯誤,應該為 JSON 陣列"
assert len(replies) == 5, f"輸出數量錯誤,應該是 5 個,但收到 {len(replies)} 個"
這段程式碼做了什麼?
assert isinstance(replies, list), "輸出格式錯誤,應該為 JSON 陣列"- 確保
replies的輸出格式為 列表 (list)。 - 如果
replies不是list,則會拋出AssertionError,終止當前測試。
- 確保
assert len(replies) == 5, f"輸出數量錯誤,應該是 5 個,但收到 {len(replies)} 個"- 確保
replies的數量正確,應該是 5 個 Quick Replies。 - 若數量不符,則拋出
AssertionError,顯示錯誤訊息。
- 確保
記錄成功測試結果
success_count += 1
response_times.append(response_time)
test_results.append({"test_case": i+1, "response_time": response_time, "quick_replies": replies})
這段程式碼做了什麼?
success_count += 1:將成功測試計數 +1。response_times.append(response_time):儲存該次測試的回應時間。test_results.append(...):將該次測試的編號、回應時間、Quick Replies 內容記錄到test_results陣列。
捕捉錯誤,記錄失敗測試
except Exception as e:
fail_count += 1
test_results.append({"test_case": i+1, "error": str(e)})
這段程式碼做了什麼?
except Exception as e:如果generate_quick_replies或assert驗證發生錯誤,則執行這段程式碼。fail_count += 1:將失敗測試計數 +1。test_results.append(...):- 紀錄測試編號。
- 儲存錯誤訊息
str(e),以便日後分析。
計算效能指標
summary = {
"total_tests": TEST_RUNS,
"success_count": success_count,
"fail_count": fail_count,
"avg_response_time": round(sum(response_times) / len(response_times), 2) if response_times else None,
"min_response_time": min(response_times) if response_times else None,
"max_response_time": max(response_times) if response_times else None
}
這段程式碼做了什麼?
total_tests: 測試總次數。success_count: 成功測試數量。fail_count: 失敗測試數量。avg_response_time: 平均回應時間(若沒有成功測試則為None)。min_response_time: 最快回應時間(若沒有成功測試則為None)。max_response_time: 最慢回應時間(若沒有成功測試則為None)。
儲存測試結果
final_data = {"summary": summary, "tests": test_results}
with open("test_results.json", "w", encoding="utf-8") as f:
json.dump(final_data, f, ensure_ascii=False, indent=4)
print("✅ 測試完成,結果已儲存至 test_results.json")
這段程式碼做了什麼?
final_data:建立一個 JSON 物件,包含:summary(總結數據)tests(每次測試的詳細資料)。
with open("test_results.json", "w", encoding="utf-8") as f:- 以寫入模式打開
test_results.json檔案。
- 以寫入模式打開
json.dump(final_data, f, ensure_ascii=False, indent=4):- 將
final_data轉成 JSON 格式,並儲存到檔案。 ensure_ascii=False:確保 JSON 中文不會變成 Unicode 轉義字符。indent=4:讓 JSON 排版更可讀。
- 將
效能監控與分析
除了驗證輸出結果的正確性,我們還需要監控 AI 生成的效能,確保回應速度符合應用需求。
監控指標
- 平均回應時間 (
avg_response_time)- 反映 AI 在多次測試中的整體回應速度。
- 若數值過高,可能代表 API 調用或 Prompt 需優化。
- 成功與失敗測試數 (
success_count/fail_count)- 若失敗率過高,需檢查 API 穩定性或輸入數據的問題。
- 最短與最長回應時間 (
min_response_time/max_response_time)- 若最大與最小回應時間差距過大,可能代表 AI 生成速度不穩定。
效能最佳化策略
- 簡化 Prompt 設計:減少不必要的上下文資訊,讓 AI 更快生成回應。
- 使用並行請求:若系統需大量請求,可考慮非同步 API 調用。
- 控制輸入數據大小:減少
chat_history、faq_list等的長度,以提高生成效率。 - 監控 API 費用與速率:避免 API 請求過多導致費用過高或速率限制。
進階測試:異常處理測試
在自動化測試中,異常測試(Edge Cases & Error Handling Tests) 是非常重要的一環。
除了確保 AI 在一般情境下運作正常,我們還需要測試在極端條件或錯誤輸入的情況下,系統是否能夠正確處理,避免崩潰或返回不合理的結果。
這些異常測試可以幫助我們:
- 提高系統穩定性:避免 API 突然失效導致整個應用崩潰。
- 增強錯誤處理能力:確保系統在遇到錯誤時能提供適當的錯誤訊息或預設回應。
- 模擬真實環境:在實際應用中,輸入數據可能會有遺漏、異常長度等狀況,因此異常測試能讓系統更健壯。
以下是三種關鍵的異常測試場景,並附上相應的測試策略與 Python 代碼示例。
模擬 API 失敗(如超時、無回應)
🔹 測試場景
- OpenAI API 可能會因為網路問題、API 伺服器負載過高、超出速率限制(Rate Limit)等原因而無法回應或回應超時。
- 我們需要確保:
- API 超時時,程式不會卡死,而是能夠返回適當的錯誤信息。
- 有適當的重試機制,當 API 短暫失敗時,可以自動重新嘗試請求。
🔹 測試策略
- 模擬 API 超時:設定 API 請求時間超過特定時間(如 5 秒)。
- 模擬 API 無回應:直接讓
generate_quick_replies返回None或拋出錯誤。
🔹 測試代碼
import requests
from generate_quick_replies import generate_quick_replies
# 測試 API 超時
try:
replies = generate_quick_replies(chat_history, faq_list, product_list, timeout=0.001) # 設定極短的超時時間
print("❌ 測試失敗,應該要超時,但仍然獲得回應:", replies)
except requests.exceptions.Timeout:
print("✅ 測試通過,API 超時處理正常。")
except Exception as e:
print(f"❌ 測試失敗,出現其他錯誤: {e}")
# 測試 API 無回應
try:
replies = None # 模擬 API 無回應
if replies is None:
raise ValueError("API 無回應")
except ValueError as e:
print("✅ 測試通過,API 無回應時系統能正常處理。")
except Exception as e:
print(f"❌ 測試失敗,出現其他錯誤: {e}")
🔹 預期結果
- API 超時時:應該拋出
requests.exceptions.Timeout,而不是讓程式卡死。 - API 無回應時:應該返回適當的錯誤訊息,避免回傳
None或錯誤數據。
測試空輸入情境(無 chat_history、faq_list、product_list)
🔹 測試場景
- 在某些情況下,AI 可能會收到空白輸入(例如剛啟動機器人時,沒有對話歷史,或 FAQ 與產品列表無資料)。
- 我們需要確保:
- AI 仍能返回預設 Quick Replies(例如:「請問有什麼我可以幫助您的?」)。
- 不會因為
None或[]而導致錯誤。
🔹 測試策略
- 測試
generate_quick_replies函式在完全無輸入數據的情況下,是否仍能提供有效回應。 - 如果沒有數據,應該提供預設回應而不是報錯。
🔹 測試代碼
try:
empty_replies = generate_quick_replies([], [], []) # 全部輸入空陣列
assert isinstance(empty_replies, list), "輸出格式錯誤,應為 JSON 陣列"
assert len(empty_replies) > 0, "應該提供預設建議回覆,而不是空陣列"
print("✅ 測試通過,空輸入時仍能生成建議回覆。")
except Exception as e:
print(f"❌ 測試失敗,空輸入處理錯誤: {e}")
🔹 預期結果
- 空輸入時:應該返回一組預設的 Quick Replies(例如:「請問有什麼我可以幫助您的?」),而不是拋出錯誤。
測試極端長度輸入(如超長的 chat_history)
🔹 測試場景
- 在實際應用中,
chat_history可能會變得非常長,如果我們不加以控制,可能會導致:- API 調用成本增加(OpenAI 會按字數計價)。
- 回應速度變慢(過長的輸入可能影響 AI 回應時間)。
- API 可能拒絕回應(輸入字數超過 API 限制)。
- 我們需要確保:
- 長輸入時,程式不會崩潰。
- 適當截斷
chat_history,只保留最近的對話。
🔹 測試策略
- 測試
chat_history含有超過 10,000 字元時,是否仍能正常運行。 - 檢查是否有機制能自動截斷對話歷史(如只保留最近 10 條訊息)。
🔹 測試代碼
long_chat_history = ["這是一條測試訊息。" * 5000] # 生成超長對話歷史
try:
replies = generate_quick_replies(long_chat_history, faq_list, product_list)
assert isinstance(replies, list), "輸出格式錯誤,應為 JSON 陣列"
print("✅ 測試通過,超長 chat_history 仍能處理。")
except Exception as e:
print(f"❌ 測試失敗,處理超長 chat_history 時出錯: {e}")
🔹 預期結果
- 超長輸入時:應該有機制截斷
chat_history,而不是讓整個 AI 計算負擔過重。
結論
異常測試可以幫助我們識別並解決潛在問題,確保 AI 在各種極端情況下都能穩定運作。我們建議將這些測試整合進 CI/CD 流程,確保系統在正式上線前已經過完整驗證。
| 測試項目 | 可能問題 | 解決方案 |
|---|---|---|
| API 失敗(超時/無回應) | 可能讓應用程式卡死 | 增加錯誤處理,並設置重試機制 |
| 空輸入(無 chat_history, faq_list, product_list) | 可能拋出錯誤 | 提供預設 Quick Replies |
| 超長輸入(chat_history 過長) | API 成本增加,回應變慢 | 截斷對話歷史,保留最近 N 條記錄 |
結論
透過自動化測試與效能監控,我們可以確保 Quick Replies 的生成符合預期,並在不同情境下保持穩定。
這不僅提升了系統的可靠性,也能幫助開發者快速發現問題,進一步優化 AI 生成的品質與效能。
你可以將這套測試機制整合到 CI/CD 流程中,自動檢測 AI 回應的品質與速度,確保你的聊天機器人始終提供高效、準確的 Quick Replies!🚀