掌握了 Koog 框架的核心技術後,讓我們把這些技術整合起來,建立一個真正實用的 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 客服系統的所有核心技術
ApiKeyManager
統一管理 API 金鑰MutableList<ConversationRecord>
儲存完整對話記錄CustomerServiceToolSet
,提供訂單查詢、營業時間查詢、FAQ 搜尋從執行結果可以看到,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筆
在 Koog 框架中,有兩種主要的對話管理方式,但它們不能直接混用
val conversationPrompt = prompt("conversation") {
system("你是友善的助手")
user("使用者問題")
}
val response = executor.execute(conversationPrompt, model)
適用場景:純對話、複雜提示結構、需要精確控制對話格式
val agent = AIAgent(
executor = executor,
systemPrompt = "你是友善的助手",
toolRegistry = toolRegistry,
llmModel = model
)
val response = agent.run("使用者輸入")
適用場景:需要工具功能、自動工具選擇、企業級應用
AIAgent
只有 run()
方法,沒有 chat()
方法選擇 prompt DSL
選擇 AIAgent + 工具系統
本文採用 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 客服機器人啟動完成!
💭 對話歷史功能已啟用
🔧 工具系統已載入:訂單查詢、營業時間、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 Agent 能夠與外部 API 服務互動
圖片來源:AI 產生
同步刊登於 Blog 第一次學 Kotlin Koog AI 就上手 Day 08:技術整合實戰:建立 AI 客服機器人