So sánh hai thư viện Java cho agent-based AI: LangChain4j và AgentScope

Khi xây dựng hệ thống trợ lý thông minh có khả năng phân tích ý định người dùng và thực thi hành động — như truy xuất tệp, tra cứu cơ sở tri thức hoặc phản hồi hướng dẫn — việc lựa chọn framework phù hợp là yếu tố then chốt. Bài viết này so sánh hai giải pháp thuần Java phổ biến: LangChain4jAgentScope, tập trung vào cách chúng xử lý intent routing, gọi hàm công cụ (tool calling), và kiểm soát luồng đầu ra — đặc biệt trong bối cảnh hiệu năng quan trọng (ví dụ: trả về kết quả từ Elasticsearch mà không qua xử lý bổ sung).

LangChain4j: Linh hoạt nhưng cần cấu hình cẩn thận

LangChain4j hỗ trợ mô hình "tool-enabled assistant" thông qua interface service và annotation @Tool. Một điểm nổi bật là thuộc tính returnBehavior = ReturnBehavior.IMMEDIATE, cho phép bỏ qua bước tổng hợp lại bởi LLM sau khi công cụ trả kết quả — giúp giảm độ trễ đáng kể khi xử lý dữ liệu thô khối lượng lớn.

Dưới đây là ví dụ tối giản sử dụng Qwen qua DashScope:

public class ToolExecutor {
    static class DataServices {
        @Tool(value = "Tính tổng hai số", returnBehavior = ReturnBehavior.IMMEDIATE)
        int computeSum(int x, int y) {
            return x + y;
        }

        @Tool(value = "Lấy thời gian hiện tại", returnBehavior = ReturnBehavior.IMMEDIATE)
        String fetchTimestamp() {
            return LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        }
    }

    interface AssistantService {
        Result<String> interact(String input);
    }

    public static void main(String[] args) {
        ChatLanguageModel model = OpenAiChatModel.builder()
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .modelName("qwen-max")
                .build();

        AssistantService agent = AiServices.builder(AssistantService.class)
                .chatModel(model)
                .tools(new DataServices())
                .build();

        Result<String> result = agent.interact("Tính tổng 7 và 9");
        result.toolExecutions().forEach(exec -> 
            System.out.println("Kết quả trực tiếp: " + exec.result())
        );
    }
}

Lưu ý: Khi dùng ReturnBehavior.IMMEDIATE, kết quả công cụ được trả về nguyên bản — không qua LLM — do đó cần xử lý Result thủ công để trích xuất exec.result() thay vì phụ thuộc vào content().

AgentScope: Thiết kế rõ ràng, API mạch lạc

AgentScope thiên về kiến trúc phản xạ (ReAct) chuẩn hóa với lớp ReActAgent và hệ thống Toolkit. Không hỗ trợ trả kết quả công cụ tức thì, nên mọi output đều đi qua mô hình — điều này yêu cầu kỹ thuật prompt engineering chặt chẽ hoặc giải pháp trung gian để đảm bảo hiệu năng.

Ví dụ triển khai nhanh:

public class AgentDemo {
    public static void main(String[] args) {
        Toolkit tools = new Toolkit();
        tools.registerTool(new QueryTools());

        ReActAgent assistant = ReActAgent.builder()
                .name("Astra")
                .sysPrompt("Bạn là trợ lý AI chuyên nghiệp, luôn trả lời ngắn gọn và chính xác.")
                .model(DashScopeChatModel.builder()
                        .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                        .modelName("qwen3-plus")
                        .build())
                .toolkit(tools)
                .build();

        Msg request = Msg.builder().textContent("Hiện tại là mấy giờ?").build();
        Msg response = assistant.call(request).block();

        System.out.println("Phản hồi: " + response.getTextContent());
    }
}

class QueryTools {
    private static final Map<String, String> CACHE = new ConcurrentHashMap<>();

    @Tool(name = "search_knowledge", description = "Tìm kiếm trong cơ sở tri thức")
    String search(@ToolParam(name = "keyword") String keyword) {
        String cacheKey = "rag:" + UUID.randomUUID();
        CACHE.put(cacheKey, "Kết quả chi tiết từ RAG: " + keyword + " — gồm 2000 ký tự...");
        return cacheKey; // Trả mã định danh thay vì nội dung đầy đủ
    }
}

Khi gọi công cụ trả về chuỗi dạng "rag:abc123", ứng dụng chủ có thể kiểm tra giá trị trả về và tra cứu nội dung thật từ CACHE — tránh việc truyền dữ liệu dài qua LLM, từ đó cắt giảm thời gian xử lý từ phút xuống dưới 1 giây.

Điểm khác biệt then chốt

  • Luồng kết quả: LangChain4j hỗ trợ bypass LLM bằng IMMEDIATE; AgentScope luôn đi qua LLM → cần thiết kế cơ chế cache hoặc placeholder.
  • API & cấu trúc: AgentScope có API rõ ràng hơn cho agent lifecycle (build/call/block); LangChain4j gắn liền với pattern interface + builder mạnh mẽ nhưng đòi hỏi hiểu sâu về ResultAiServices.
  • Mở rộng công cụ: Cả hai đều hỗ trợ tham số phức tạp (List, custom object), nhưng AgentScope yêu cầu chú thích @ToolParam tường minh hơn cho mỗi tham số.

Thẻ: langchain4j AgentScope java-ai tool-calling react-agent

Đăng vào ngày 29 tháng 6 lúc 10:56