- Published on
第一次學 Kotlin Koog AI 就上手 Day 08:技術整合實戰:建立 AI 客服機器人
掌握了 Koog 框架的核心技術後,讓我們把這些技術整合起來,建立一個真正實用的 AI 客服機器人!
所需核心技術
基礎架構技術
- AI Agent 建立:學會建立和配置基本的 AI Agent 程式
- API 整合:掌握多個 LLM 提供商的基本整合方法
AI 對話技術
- 提示工程:設計有效的系統提示來引導 AI 行為
- 工具整合:了解基礎工具系統的使用方法
接下來我們要把這些技術組合起來,建立一個專注於對話功能的 AI 客服機器人
AI 客服機器人實作
現在讓我們把前面學到的技術組合起來,建立一個完整的 AI 客服機器人
/**
* 對話紀錄資料結構 - 用來儲存對話歷史
*/
data class ConversationRecord(
val userMessage: String,
val assistantResponse: String,
val timestamp: Long = System.currentTimeMillis()
)
/**
* 客服工具集 - 提供實用的客服功能
*/
@LLMDescription("客服工具集,包含訂單查詢、營業時間查詢和常見問題搜尋")
class CustomerServiceToolSet : ToolSet {
@Tool
@LLMDescription("查詢訂單狀態和配送資訊")
fun lookupOrder(
@LLMDescription("訂單編號,格式如 ORD-20241201-001")
orderId: String
): String {
return try {
// 模擬訂單查詢邏輯
when {
orderId.isBlank() -> "請提供有效的訂單編號"
orderId.startsWith("ORD-") -> {
val randomStatus = listOf(
"已確認,預計 3-5 個工作天送達",
"已出貨,配送中,預計明天送達",
"已送達,感謝您的購買",
"處理中,我們正在準備您的商品"
).random()
"訂單 $orderId 狀態:$randomStatus"
}
else -> "訂單編號格式不正確,請確認後重新輸入"
}
} catch (e: Exception) {
"查詢訂單時發生錯誤:${e.message}"
}
}
@Tool
@LLMDescription("查詢指定門市或地區的營業時間")
fun getBusinessHours(
@LLMDescription("門市名稱或地區,如:台北、高雄、台中")
location: String
): String {
return try {
val businessHours = mapOf(
"台北" to "週一至週日 9:00-22:00",
"台中" to "週一至週日 10:00-21:00",
"高雄" to "週一至週日 9:30-21:30",
"桃園" to "週一至週日 9:00-21:00",
"台南" to "週一至週日 10:00-20:00"
)
val normalizedLocation = location.trim()
businessHours[normalizedLocation]
?: "目前僅提供台北、台中、高雄、桃園、台南地區的營業時間查詢。一般門市營業時間為週一至週日 9:00-21:00"
} catch (e: Exception) {
"查詢營業時間時發生錯誤:${e.message}"
}
}
@Tool
@LLMDescription("搜尋常見問題的解答")
fun searchFaq(
@LLMDescription("問題關鍵字,如:退款、配送、會員")
keyword: String
): String {
return try {
val faqDatabase = mapOf(
"退款" to "退款政策:商品收到後 7 天內可申請退款,商品需保持原包裝。退款處理時間約 7-14 個工作天。",
"配送" to "配送時間:一般商品 3-5 個工作天,急件可選擇隔日配送(需加收費用)。",
"會員" to "會員權益:免費註冊即享 95 折優惠,消費滿額可累積點數兌換禮品。",
"保固" to "保固服務:電子產品提供 1 年保固,非人為損壞免費維修。",
"客服" to "客服時間:週一至週五 9:00-18:00,客服專線:0800-123-456"
)
val result = faqDatabase.entries.find {
it.key.contains(keyword) || keyword.contains(it.key)
}
result?.value ?: "很抱歉,沒有找到相關的常見問題。您可以嘗試其他關鍵字,或直接聯絡客服人員協助。"
} catch (e: Exception) {
"搜尋常見問題時發生錯誤:${e.message}"
}
}
}
/**
* AI 客服機器人 - 整合前面學習的核心技術
* 專注於對話功能,提供友善的客服體驗,並支援對話歷史和工具系統
*/
class SmartCustomerService {
// 對話歷史儲存 - 使用簡單的 MutableList
private val conversationHistory = mutableListOf<ConversationRecord>()
// 工具註冊 - 包含客服相關工具
private val toolRegistry = ToolRegistry {
tools(CustomerServiceToolSet())
}
// AI Agent - 整合執行器、工具和提示
private val agent = AIAgent(
executor = simpleOpenAIExecutor(ApiKeyManager.openAIApiKey!!),
systemPrompt = createCustomerServicePrompt(),
toolRegistry = toolRegistry,
llmModel = OpenAIModels.CostOptimized.GPT4_1Mini,
temperature = 0.7
)
init {
println("🤖 AI 客服機器人啟動完成!")
println("💭 對話歷史功能已啟用")
println("🔧 工具系統已載入:訂單查詢、營業時間、FAQ 搜尋")
}
// 專業客服提示系統設計
private fun createCustomerServicePrompt(): String {
return """
你是一個專業、友善的 AI 客服助手,名字叫「9527」
你的服務原則:
1. 用正體中文回答,語調親切專業
2. 耐心解答客戶的各種問題
3. 提供清楚、有用的資訊
4. 記住之前的對話內容,提供連貫的服務
5. 遇到複雜問題時,建議客戶聯絡真人客服
你有以下工具可以使用:
- lookupOrder:查詢訂單狀態,需要客戶提供訂單編號
- getBusinessHours:查詢門市營業時間,可以指定地區
- searchFaq:搜尋常見問題解答,根據關鍵字查找
使用工具的時機:
- 客戶詢問訂單狀態時,使用 lookupOrder 工具
- 客戶詢問營業時間時,使用 getBusinessHours 工具
- 客戶有一般性問題時,使用 searchFaq 工具搜尋相關解答
請記住,你的目標是讓每位客戶都感受到溫暖的服務體驗
""".trimIndent()
}
/**
* 處理客戶問題 - 核心對話功能,支援對話歷史和工具系統
*/
suspend fun chat(customerMessage: String): String {
return try {
// 建立包含對話歷史的完整輸入
val fullInput = buildString {
// 加入對話歷史作為上下文
if (conversationHistory.isNotEmpty()) {
appendLine("=== 對話歷史 ===")
conversationHistory.takeLast(5).forEach { record -> // 只取最近 5 輪對話
appendLine("客戶:${record.userMessage}")
appendLine("9527:${record.assistantResponse}")
}
appendLine("=== 當前問題 ===")
}
append(customerMessage)
}
// 使用 AIAgent 處理客戶問題(自動包含工具使用)
val assistantResponse = agent.run(fullInput)
// 儲存到對話歷史
conversationHistory.add(
ConversationRecord(
userMessage = customerMessage,
assistantResponse = assistantResponse
)
)
assistantResponse
} catch (e: Exception) {
// 健全的錯誤處理機制
println("處理對話時發生錯誤:${e.message}")
"很抱歉,我現在遇到一些技術問題。請稍後再試,或直接撥打客服專線。"
}
}
/**
* 取得對話歷史統計資訊
*/
fun getConversationStats(): String {
return "📊 目前已進行 ${conversationHistory.size} 輪對話"
}
/**
* 清除對話歷史
*/
fun clearHistory() {
conversationHistory.clear()
println("🗑️ 對話歷史已清除")
}
/**
* 開始互動式對話 - 使用 while 迴圈實現連續對話
*/
suspend fun startInteractiveChat() {
println("🎉 歡迎使用 AI 客服系統")
println("💬 您可以開始提問,輸入 'exit' 結束對話,輸入 'stats' 查看統計")
println("=".repeat(50))
while (true) {
print("\n💬 您的問題:")
val input = readlnOrNull()?.trim()
when {
input.isNullOrEmpty() -> continue
input.lowercase() == "exit" -> {
println("👋 感謝使用 AI 客服系統,祝您有美好的一天!")
println(getConversationStats())
break
}
input.lowercase() == "stats" -> {
println(getConversationStats())
continue
}
input.lowercase() == "clear" -> {
clearHistory()
continue
}
else -> {
try {
print("🤖 9527 回應中...")
val response = chat(input)
print("\r🤖 9527:$response\n")
println("-".repeat(50))
} catch (e: Exception) {
println("⚠️ 系統錯誤:${e.message}")
}
}
}
}
}
}
這個 SmartCustomerService
實作雖然簡潔,但整合了 AI 客服系統的所有核心技術
- API 管理:使用
ApiKeyManager
統一管理 API 金鑰 - 提示工程:設計專業的客服提示系統,塑造友善的服務語調
- 對話歷史:使用
MutableList<ConversationRecord>
儲存完整對話記錄 - 上下文管理:透過結構化字串將歷史對話傳遞給 AI,實現記憶功能
- 工具系統:整合客服專用工具
CustomerServiceToolSet
,提供訂單查詢、營業時間查詢、FAQ 搜尋 - 自動工具選擇:AI 會根據客戶問題自動選擇適合的工具
- 模型選擇:選擇適合的 GPT-4.1 mini 模型,平衡性能與成本 (實際要用什麼模型,自己可以根據需求和成本來調整)
- 互動式介面:使用 while 迴圈實現連續對話,支援多種指令
對話歷史功能特色
記憶能力展示
從執行結果可以看到,AI 客服現在具備了真正的記憶能力
- 上下文引用:AI 能準確回答「我剛才問的是什麼問題?」
- 情境延續:當客戶說「剛才我提到的訂單」時,AI 能理解並連結之前的對話
- 個人化服務:記住客戶是「新客戶」,在後續回應中提供相應的服務
技術實作要點
資料結構設計
data class ConversationRecord(
val userMessage: String,
val assistantResponse: String,
val timestamp: Long = System.currentTimeMillis()
)
使用簡單的 data class 和 MutableList,避免過度複雜的設計
對話歷史整合
val fullInput = buildString {
if (conversationHistory.isNotEmpty()) {
appendLine("=== 對話歷史 ===")
conversationHistory.takeLast(5).forEach { record ->
appendLine("客戶:${record.userMessage}")
appendLine("9527:${record.assistantResponse}")
}
appendLine("=== 當前問題 ===")
}
append(customerMessage)
}
val response = agent.run(fullInput)
將對話歷史以結構化方式整合到輸入中,配合 AIAgent 的工具系統,讓 AI 能「看到」完整的對話脈絡並自動選擇工具
要注意的是,這裡暫時不考慮歷史對話遺失的問題,這裡只拿最後 5筆
重要技術限制
prompt DSL 與工具系統的選擇
在 Koog 框架中,有兩種主要的對話管理方式,但它們不能直接混用
prompt DSL
val conversationPrompt = prompt("conversation") {
system("你是友善的助手")
user("使用者問題")
}
val response = executor.execute(conversationPrompt, model)
適用場景:純對話、複雜提示結構、需要精確控制對話格式
AIAgent + 工具系統
val agent = AIAgent(
executor = executor,
systemPrompt = "你是友善的助手",
toolRegistry = toolRegistry,
llmModel = model
)
val response = agent.run("使用者輸入")
適用場景:需要工具功能、自動工具選擇、企業級應用
為什麼不能混用?
- API 設計限制:
AIAgent
只有run()
方法,沒有chat()
方法 - 架構差異:prompt DSL 直接操作 executor,AIAgent 封裝了工具處理邏輯
- 控制層級:prompt DSL 提供低階控制,AIAgent 提供高階封裝
實際選擇建議
選擇 prompt DSL
- 需要精確控制對話格式
- 實作複雜的多輪對話邏輯
- 不需要工具功能
- 追求最大彈性
選擇 AIAgent + 工具系統
- 需要 AI 自動使用工具
- 建立實用的應用系統
- 追求開發效率
- 需要企業級功能
本文採用 AIAgent 方式,因為客服機器人需要訂單查詢、營業時間查詢等實用工具功能
工具系統整合特色
實用工具展示
我們為客服機器人整合了三個實用的工具
訂單查詢工具 (lookupOrder)
- 模擬查詢真實訂單狀態
- 支援訂單編號格式驗證
- 提供配送進度資訊
營業時間查詢工具 (getBusinessHours)
- 支援多地區門市查詢
- 涵蓋台北、台中、高雄、桃園、台南
- 提供詳細營業時間資訊
FAQ 搜尋工具 (searchFaq)
- 內建常見問題資料庫
- 支援關鍵字模糊搜尋
- 涵蓋退款、配送、會員、保固等主題
技術實作要點
Annotation-based 工具設計
@Tool
@LLMDescription("查詢訂單狀態和配送資訊")
fun lookupOrder(
@LLMDescription("訂單編號,格式如 ORD-20241201-001")
orderId: String
): String
使用註解方式快速建立工具,程式碼簡潔易懂
工具選擇
private val toolRegistry = ToolRegistry {
tools(CustomerServiceToolSet())
}
註冊相關的工具後,AI 會根據客戶問題自動選擇合適的工具,無需手動指定
使用示範
suspend fun main() {
println("🎉 AI 客服機器人技術展示")
println("=".repeat(35))
// 建立客服機器人實例
val chatbot = SmartCustomerService()
// 模擬一些客戶對話 - 現在有上下文記憶和工具使用
val conversations = listOf(
"你好!我想了解你們的服務",
"請問台北門市的營業時間?", // 測試營業時間查詢工具
"我想查詢訂單 ORD-20241201-001 的狀態", // 測試訂單查詢工具
"請問你們的退款政策是什麼?", // 測試 FAQ 搜尋工具
"我剛才查詢的訂單如果要退款該怎麼辦?", // 測試記憶功能 + FAQ
"謝謝你的協助!"
)
// 逐一進行對話
conversations.forEachIndexed { index, message ->
println("\n💬 客戶:$message")
val response = chatbot.chat(message)
println("🤖 9527:$response")
// 顯示對話統計
if (index == conversations.size - 1) {
println("\n${chatbot.getConversationStats()}")
}
// 模擬對話間隔
delay(1000)
}
println("\n🎊 對話測試完成!")
}
執行 AI 回應內容
🎉 AI 客服機器人技術展示
===================================
🤖 AI 客服機器人啟動完成!
💭 對話歷史功能已啟用
🔧 工具系統已載入:訂單查詢、營業時間、FAQ 搜尋
💬 客戶:你好!我想了解你們的服務
🤖 9527:您好!很高興為您服務。我是9527,您的專屬AI客服助理。請問您想了解我們哪方面的服務呢?像是訂單查詢、商品資訊、退款政策、門市營業時間等,我都可以為您說明喔!如果您有具體問題,也歡迎隨時告訴我。
💬 客戶:請問台北門市的營業時間?
🤖 9527:台北門市的營業時間是週一至週日的上午9點到晚上10點。如果您還有其他問題,隨時告訴我喔!
💬 客戶:我想查詢訂單 ORD-20241201-001 的狀態
🤖 9527:您的訂單 ORD-20241201-001 目前狀態是「處理中」,我們正在準備您的商品。如果您需要進一步協助,隨時告訴我喔!
💬 客戶:請問你們的退款政策是什麼?
🤖 9527:您好,我們的退款政策是:商品收到後 7 天內可申請退款,且商品需保持原包裝。退款處理時間約為 7-14 個工作天。如果您有其他問題,或需要協助申請退款,請隨時告訴我喔!
💬 客戶:我剛才查詢的訂單如果要退款該怎麼辦?
🤖 9527:您好!如果您想對訂單 ORD-20241201-001 申請退款,請您確認商品是在收到後7天內,且商品包裝保持完整。接著您可以透過我們的官方客服管道提交退款申請,通常需要提供訂單編號和退款原因。我可以幫您提供退款申請的詳細流程或協助聯繫真人客服,請問您需要嗎?
💬 客戶:謝謝你的協助!
🤖 9527:不客氣!很高興能幫助到您。如果之後還有任何問題或需要協助,隨時歡迎找我喔。祝您有美好的一天!😊
📊 目前已進行 6 輪對話
🎊 對話測試完成!
總結
通過建立這個 AI 客服機器人,我們成功示範了如何整合 Koog 框架的核心技術
API 管理與安全
- 建立統一的
ApiKeyManager
來管理 API 金鑰 - 避免在程式碼中散布敏感資訊,提升系統安全性
- 建立統一的
提示工程與對話設計
- 學會撰寫清楚、專業的系統提示
- 掌握如何透過提示引導 AI 的行為和語調
工具系統整合
- 建立實用的客服工具集(訂單查詢、營業時間、FAQ 搜尋)
- 使用 Annotation-based 方式快速開發工具
- 讓 AI 智能選擇合適的工具解決客戶問題
架構設計選擇
- 理解 prompt DSL 與 AIAgent 工具系統的差異和限制
- 學會根據需求選擇合適的實作方式
- 掌握工具系統的優勢和適用場景
下一篇文章中,我們將學習如何開發非同步工具,讓 AI Agent 能夠與外部 API 服務互動
參考資料
支持創作
如果這篇文章對您有幫助,歡迎透過 贊助連結 支持我持續創作優質內容。您的支持是我前進的動力!
圖片來源:AI 產生