iT邦幫忙

2025 iThome 鐵人賽

DAY 2
0
生成式 AI

Java AI 核心引擎:30 天從零打造可擴展的智慧 Agent 函式庫系列 第 2

Day 2:首次對話:ChatLanguageModel 的基本使用

  • 分享至 

  • xImage
  •  

Java AI 核心引擎:30 天從零打造可擴展的智慧 Agent 函式庫
本篇是 IT 鐵人賽系列文章的第二天,將使用 LangChain4j 的基礎模型 API 進行最直接的 AI 互動。

今日目標

  • 設定 Ollama 模型連線參數
  • 注入並使用 ChatLanguageModel Bean
  • 建立 CommandLineRunner 執行啟動任務
  • 完成第一次 AI 對話並驗證結果

開始前的環境檢查

確保昨天的基礎沒問題

在開始今天精彩的 AI 對話之前,我們先花一分鐘確認昨天建立的環境都運作正常。這個檢查步驟雖然看似瑣碎,但能避免後面遇到奇怪的問題時不知道從哪裡開始除錯。

# 檢查 Ollama 服務是否正常回應
curl http://localhost:11434/api/version

# 確認我們的 Llama 模型已經下載
ollama list | grep llama3.1

如果這兩個指令都能正常回傳結果,那就表示我們的 AI 基礎環境已經準備就緒!

Maven 依賴檢查

確認 pom.xml 中已包含 LangChain4j 依賴(Day 1 已設定):

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-spring-boot-starter</artifactId>
    <version>0.36.2</version>
</dependency>

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
    <version>0.36.2</version>
</dependency>

認識我們的第一個 AI 夥伴:ChatLanguageModel

為什麼從 ChatLanguageModel 開始?

ChatLanguageModel 是 LangChain4j 框架中最基礎也是最重要的介面。我喜歡把它想像成是一座橋樑,連接我們的 Java 程式碼和背後強大的語言模型。

從開發者的角度來看,它有幾個讓人愛不釋手的特點:

  • 同步且簡單:發送一個請求,等待一個完整的回應,就這麼直觀
  • 介面簡潔:主要就是一個 generate() 方法,使用成本很低
  • 自動配置:感謝 Spring Boot Starter,我們幾乎不需要寫任何配置程式碼
  • 模型無關:今天用 Ollama,明天想換 OpenAI 也沒問題,介面保持一致

這種設計哲學很符合 Java 開發者的習慣,不會有太多意外的驚喜,但也不會有令人頭痛的複雜性。

重要方法

public interface ChatLanguageModel {
    // 簡單對話:輸入字串,回傳字串
    String generate(String userMessage);
    
    // 進階對話:使用 ChatMessage 物件
    Response<AiMessage> generate(ChatMessage... messages);
}

動手實作:第一個 AI 對話程式

建立我們的對話測試程式

現在到了最興奮的時刻!我們要建立第一個能和 AI 對話的 Java 程式。我選擇使用 CommandLineRunner 這個方式,因為它會在 Spring Boot 應用程式啟動完成後自動執行,非常適合我們做測試和驗證。

src/main/java/org/example/aiagentdemo/runner 目錄下建立一個新的類別:

package org.example.aiagentdemo.runner;

import dev.langchain4j.model.chat.ChatLanguageModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

/**
 * AI 對話執行器 - 應用程式啟動後自動執行
 * 
 * 使用 CommandLineRunner 介面,在 Spring Boot 應用程式啟動完成後
 * 自動執行 run 方法中的程式碼
 */
@Component
public class AiChatRunner implements CommandLineRunner {
    
    private static final Logger logger = LoggerFactory.getLogger(AiChatRunner.class);
    
    // 注入 LangChain4j 自動配置的 ChatLanguageModel Bean
    @Autowired
    private ChatLanguageModel chatLanguageModel;
    
    @Override
    public void run(String... args) throws Exception {
        logger.info("========== 開始 AI 對話測試 ==========");
        
        // 測試 1:簡單問候
        testSimpleGreeting();
        
        // 測試 2:技術問題
        testTechnicalQuestion();
        
        // 測試 3:繁體中文對話
        testChineseConversation();
        
        logger.info("========== AI 對話測試完成 ==========");
    }
    
    /**
     * 測試簡單問候
     */
    private void testSimpleGreeting() {
        logger.info("\n--- 測試 1:簡單問候 ---");
        String question = "你好!今天過得如何?";
        logger.info("使用者: {}", question);
        
        String response = chatLanguageModel.generate(question);
        logger.info("AI 回應: {}", response);
    }
    
    /**
     * 測試技術問題
     */
    private void testTechnicalQuestion() {
        logger.info("\n--- 測試 2:技術問題 ---");
        String question = "什麼是 Spring Boot?請用兩句話說明。";
        logger.info("使用者: {}", question);
        
        String response = chatLanguageModel.generate(question);
        logger.info("AI 回應: {}", response);
    }
    
    /**
     * 測試繁體中文對話
     */
    private void testChineseConversation() {
        logger.info("\n--- 測試 3:繁體中文對話 ---");
        String question = "請用繁體中文解釋什麼是 AI Agent,限 50 字以內。";
        logger.info("使用者: {}", question);
        
        String response = chatLanguageModel.generate(question);
        logger.info("AI 回應: {}", response);
    }
}

步驟 2:更新應用程式配置

確認 application.properties 中的配置(沿用 Day 1 設定):

spring.application.name=ai-agent-demo

# Ollama Configuration
langchain4j.ollama.chat-model.base-url=http://localhost:11434
langchain4j.ollama.chat-model.model-name=llama3.1:8b-instruct-q4_K_M
langchain4j.ollama.chat-model.temperature=0.7
langchain4j.ollama.chat-model.timeout=PT5M

# 日誌等級設定 - 顯示詳細的 AI 互動日誌
logging.level.org.example.aiagentdemo=INFO
logging.level.dev.langchain4j=DEBUG

執行與測試

啟動應用程式

./mvnw spring-boot:run

預期輸出

成功執行後,您應該會看到類似以下的輸出:

INFO --- [main] o.e.aiagentdemo.AiChatRunner : ========== 開始 AI 對話測試 ==========

INFO --- [main] o.e.aiagentdemo.AiChatRunner : --- 測試 1:簡單問候 ---
INFO --- [main] o.e.aiagentdemo.AiChatRunner : 使用者: 你好!今天過得如何?
INFO --- [main] o.e.aiagentdemo.AiChatRunner : AI 回應: 你好!我是一個 AI 助理,隨時準備好為您提供協助。今天我運作正常,謝謝您的關心!有什麼可以幫助您的嗎?

INFO --- [main] o.e.aiagentdemo.AiChatRunner : --- 測試 2:技術問題 ---
INFO --- [main] o.e.aiagentdemo.AiChatRunner : 使用者: 什麼是 Spring Boot?請用兩句話說明。
INFO --- [main] o.e.aiagentdemo.AiChatRunner : AI 回應: Spring Boot 是建立在 Spring 框架之上的開發框架,透過自動配置和內嵌伺服器大幅簡化了 Java 應用程式的開發。它消除了傳統 Spring 應用中大量的樣板程式碼和 XML 配置需求。

INFO --- [main] o.e.aiagentdemo.AiChatRunner : --- 測試 3:繁體中文對話 ---
INFO --- [main] o.e.aiagentdemo.AiChatRunner : 使用者: 請用繁體中文解釋什麼是 AI Agent,限 50 字以內。
INFO --- [main] o.e.aiagentdemo.AiChatRunner : AI 回應: AI Agent 是能自主執行任務的人工智慧系統,可感知環境、做出決策並採取行動來達成特定目標。

INFO --- [main] o.e.aiagentdemo.AiChatRunner : ========== AI 對話測試完成 ==========

深入理解背後的運作原理

Spring Boot 的自動配置魔法

當我們第一次看到 @Autowired 就能直接注入 ChatLanguageModel 時,可能會覺得有點神奇。這背後其實是 Spring Boot 自動配置機制的功勞。

當我們在 pom.xml 中加入 langchain4j-ollama-spring-boot-starter 依賴後,Spring Boot 在啟動時會自動:

  1. 掃描配置檔案:從 application.properties 中尋找所有 langchain4j.ollama.* 開頭的配置
  2. 建立連線物件:根據配置建立與 Ollama API 的 HTTP 連線
  3. 註冊 Bean:將 ChatLanguageModel 的實作類別註冊為 Spring Bean

這就是為什麼我們不需要寫任何複雜的初始化程式碼,Spring Boot 都幫我們處理好了。

CommandLineRunner 執行時機

應用程式啟動流程:
1. Spring Context 初始化
2. 所有 Bean 建立完成
3. 應用程式完全啟動
4. 執行所有 CommandLineRunner 的 run() 方法  <-- 我們的測試在這裡執行
5. 應用程式進入運行狀態

generate() 方法的運作流程

根據 Ollama API 文件,當呼叫 generate() 方法時,LangChain4j 會透過 HTTP 與 Ollama API 進行通訊:

// 當呼叫:
String response = chatLanguageModel.generate("Hello!");

// 從實作細節分析,LangChain4j 內部處理流程如下:
// 1. 將使用者訊息轉換為 Ollama API 格式
// 2. 發送 POST 請求到 /api/chat 端點
//    API 文件說明:「Generate the next message in a chat with a provided model. 
//    This is a streaming endpoint, so there will be a series of responses. 
//    Streaming can be disabled using "stream": false.」
// 3. Ollama 服務處理請求並回傳串流或完整回應
// 4. LangChain4j 解析回應並回傳字串結果

API 請求格式範例(來自官方文件):

{
  "model": "llama3.2",
  "messages": [
    {
      "role": "user", 
      "content": "why is the sky blue?"
    }
  ]
}

(上述為官方文件原始範例)

在 LangChain4j 中使用時,實際請求會是:

{
  "model": "llama3.1:8b-instruct-q4_K_M",
  "messages": [
    {"role": "user", "content": "Hello!"}
  ],
  "stream": false
}

(模型名稱和 stream 設定根據 LangChain4j 的預設配置)


注意事項

問題 1:連線被拒絕

錯誤訊息

Connection refused: localhost/127.0.0.1:11434

解決方法

# 確認 Ollama 服務正在運行
ollama serve

# 或在另一個終端機執行任何 ollama 命令來啟動服務
ollama list

總結

今日完成項目

  • 成功注入並使用 ChatLanguageModel Bean
  • 實作 CommandLineRunner 自動執行測試
  • 完成三種不同類型的 AI 對話測試
  • 驗證中英文對話能力

今天的重要收穫

  1. ChatLanguageModel 的簡潔威力:一個介面,一個方法,就能和 AI 對話
  2. Spring Boot 自動配置的神奇:幾行配置就能完成複雜的連線設定
  3. 同步對話的直觀性generate() 方法讓 AI 互動變得和普通方法呼叫一樣簡單
  4. Llama 3.1 的語言能力:繁體中文支援出乎意料地好

最讓我印象深刻的是,從寫程式碼到看到 AI 回應,整個過程竟然如此順暢。這就是好的框架設計帶來的威力。

明日預告:Day 3 - 聲明式魔法:透過 AiServices 將 Java 介面轉換為 AI 服務

明天將:

  • 實作使用 @AiService 註解
  • 定義自訂的 Assistant 介面
  • 實現更優雅的 AI 服務開發方式
  • 比較直接使用 ChatLanguageModel 與 AiServices 的差異

參考資料


感謝大家的閱讀,我們明天見!

Day 2 完成 | 明天繼續我們的 AI 冒險之旅!


上一篇
Day 1:擁抱框架:認識 LangChain4j 與設定開發環境
下一篇
Day 3:聲明式魔法:透過 AiServices 將 Java 介面轉換為 AI 服務
系列文
Java AI 核心引擎:30 天從零打造可擴展的智慧 Agent 函式庫3
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言