0
0
Lập trình
NM

Xây dựng Giao diện Trò chuyện: Từ Thành phần đến Đối thoại

Đăng vào 3 tuần trước

• 8 phút đọc

Chủ đề:

#ai#mcp#java#llm

Phần 6 trong chuỗi bài viết "Từ Con số đến Đại lý AI: Hành trình của tôi vào Ứng dụng Thông minh dựa trên Java"

Chúng ta đã xây dựng tất cả các thành phần cốt lõi: MCPService để kết nối công cụ (Bài 3), LLMClient cho trí thông minh AI (Bài 4), và SimpleInference cho xử lý truy vấn thông minh (Bài 5). Giờ là lúc kết hợp mọi thứ lại thành một thứ mà mọi người có thể sử dụng: một giao diện trò chuyện đơn giản.

Hôm nay, chúng ta sẽ tạo một ứng dụng trò chuyện tối thiểu nhưng chức năng, giúp tương tác với các công cụ MCP trở nên tự nhiên hơn.

Mục tiêu: Đối thoại đơn giản

Thay vì các lệnh phức tạp, người dùng nên có thể trò chuyện một cách tự nhiên:

Copy
AI Trợ lý đã sẵn sàng! Gõ 'exit' để thoát.

Bạn: Thời tiết hôm nay thế nào?
Trợ lý: Thời tiết hiện tại là 22°C với bầu trời có mây.

Bạn: Lưu thông tin đó vào weather.txt 
Trợ lý: Tôi đã lưu thông tin thời tiết vào weather.txt thành công.

Bạn: exit
Trợ lý: Tạm biệt!

Đơn giản, rõ ràng, và chức năng.

Lớp ChatInterface

Dưới đây là giao diện trò chuyện hoàn chỉnh của chúng ta - đơn giản hơn bạn nghĩ:

Copy
import java.util.Scanner;

public class ChatInterface {
    private final SimpleInference inference; // Từ Bài 5
    private final MCPService mcpService;     // Từ Bài 3
    private final Scanner scanner;
    private boolean running = true;

    public ChatInterface(MCPService mcpService, LLMClient llmClient) {
        this.mcpService = mcpService;
        this.inference = new SimpleInference(mcpService, llmClient);
        this.scanner = new Scanner(System.in);
    }

    public void startChat() {
        showWelcome();

        while (running) {
            String input = getUserInput();

            if (isExitCommand(input)) {
                running = false;
                System.out.println("Tạm biệt!");
                continue;
            }

            processUserQuery(input);
        }

        cleanup();
    }

    private void showWelcome() {
        List<Tool> tools = mcpService.getAllAvailableTools();
        System.out.println("AI Trợ lý đã sẵn sàng! Kết nối với " + tools.size() + " công cụ.");
        System.out.println("Gõ 'exit' để thoát.\n");
    }

    private String getUserInput() {
        System.out.print("Bạn: ");
        return scanner.nextLine().trim();
    }

    private boolean isExitCommand(String input) {
        String lower = input.toLowerCase();
        return lower.equals("exit") || lower.equals("quit") || lower.equals("bye");
    }

    private void processUserQuery(String input) {
        if (input.isEmpty()) {
            return;
        }

        try {
            String response = inference.processQuery(input);
            System.out.println("Trợ lý: " + response + "\n");

        } catch (Exception e) {
            System.out.println("Xin lỗi, tôi gặp lỗi: " + e.getMessage() + "\n");
        }
    }

    private void cleanup() {
        scanner.close();
        mcpService.close();
    }
}

Vậy là xong! Một lớp, sáu phương thức, mọi thứ hoạt động.

Ứng dụng hoàn chỉnh

Dưới đây là cách kết nối mọi thứ lại với nhau:

Copy
public class ChatApp {
    public static void main(String[] args) {
        try {
            // Khởi tạo các thành phần từ các bài trước
            MCPService mcpService = new MCPService();
            LLMClient llmClient = createLLMClient();

            // Bắt đầu trò chuyện
            ChatInterface chat = new ChatInterface(mcpService, llmClient);
            chat.startChat();

        } catch (Exception e) {
            System.err.println("Không thể khởi động: " + e.getMessage());
        }
    }

    private static LLMClient createLLMClient() {
        String groqKey = System.getenv("GROQ_API_KEY");
        if (groqKey != null && !groqKey.isEmpty()) {
            return LLMClientFactory.createGroqClient(groqKey);
        }

        String geminiKey = System.getenv("GEMINI_API_KEY");
        if (geminiKey != null && !geminiKey.isEmpty()) {
            return LLMClientFactory.createGeminiClient(geminiKey);
        }

        throw new RuntimeException("Đặt biến môi trường GROQ_API_KEY hoặc GEMINI_API_KEY");
    }
}

Ví dụ về Đối thoại Thực tế

Dưới đây là một ví dụ về cuộc trò chuyện thực tế:

Copy
AI Trợ lý đã sẵn sàng! Kết nối với 8 công cụ.
Gõ 'exit' để thoát.

Bạn: thời tiết ở Tokyo thế nào?
Trợ lý: Thời tiết hiện tại ở Tokyo là 22°C với bầu trời có mây và gió nhẹ.

Bạn: lưu thông tin đó vào weather-tokyo.txt
Trợ lý: Tôi đã lưu thông tin thời tiết vào weather-tokyo.txt thành công.

Bạn: liệt kê các tệp của tôi
Trợ lý: Tôi tìm thấy 4 tệp trong thư mục hiện tại của bạn: weather-tokyo.txt, config.json, notes.md, và data.csv.

Bạn: 2+2 bằng bao nhiêu?
Trợ lý: 2+2 bằng 4. Đây là phép cộng cơ bản.

Bạn: đọc tệp thời tiết
Trợ lý: Tệp thời tiết chứa: Thời tiết hiện tại ở Tokyo là 22°C với bầu trời có mây và gió nhẹ.

Bạn: exit
Trợ lý: Tạm biệt!

Chú ý cách nó xử lý một cách mượt mà:

  • Truy vấn thời tiết sử dụng các công cụ thời tiết MCP
  • Hoạt động với tệp có ngữ cảnh ("đó" đề cập đến dữ liệu thời tiết)
  • Câu hỏi trực tiếp sử dụng kiến thức LLM
  • Tham chiếu ngữ cảnh giữa các truy vấn

Điểm nổi bật của Tích hợp

Giao diện trò chuyện của chúng ta đã thành công trong việc sử dụng tất cả các thành phần từ các bài trước:

MCPService (Bài 3):

Copy
mcpService.getAllAvailableTools()  // Hiện trạng kết nối
mcpService.close()                 // Dọn dẹp khi thoát
// Được sử dụng nội bộ bởi SimpleInference để thực thi công cụ

LLMClient (Bài 4):

Copy
LLMClientFactory.createGroqClient(apiKey)  // Tạo client
// Được sử dụng nội bộ bởi SimpleInference cho trí thông minh

SimpleInference (Bài 5):

Copy
inference.processQuery(input)  // Xử lý truy vấn chính
// Xử lý phân tích, chọn công cụ, trích xuất tham số

Tất cả đều hoạt động cùng nhau một cách mượt mà mà không có sự phức tạp thêm nào.

Xử lý Lỗi

Cách tiếp cận đơn giản của chúng ta để xử lý lỗi:

Copy
private void processUserQuery(String input) {
    if (input.isEmpty()) {
        return;
    }

    try {
        String response = inference.processQuery(input);
        System.out.println("Trợ lý: " + response + "\n");

    } catch (Exception e) {
        System.out.println("Xin lỗi, tôi gặp lỗi: " + e.getMessage() + "\n");
    }
}

Tại sao Cách tiếp cận Đơn giản này Hiệu quả

Chúng ta đang sử dụng một cách tiếp cận rất đơn giản cho dự án này vì mục đích giáo dục, nhằm tạo điều kiện cho việc hiểu và học tập. Trò chuyện không phải là trọng tâm chính của chúng ta mà là một công cụ bổ sung để minh họa các khái niệm một cách rõ ràng.

Chạy Ứng dụng

Đặt API key của bạn:

Copy
   export GROQ_API_KEY=your_key_here

Cài đặt các máy chủ MCP:

Copy
   npm install -g @modelcontextprotocol/server-weather
   npm install -g @modelcontextprotocol/server-filesystem

Chạy trò chuyện:

Copy
   # Biên dịch dự án
   mvn compile

   # Chạy trò chuyện tương tác
   mvn exec:java -Dexec.mainClass="com.gazapps.ChatApp"

Bắt đầu trò chuyện một cách tự nhiên!

Hạn chế Hiện tại

Cách tiếp cận đơn giản của chúng ta có một số hạn chế cố ý:

  • Chỉ một người dùng - Không hỗ trợ đa phiên
  • Ngữ cảnh cơ bản - Chỉ nhớ kết quả cuối cùng cho các tham chiếu "đó"
  • Chỉ dòng lệnh - Chưa có giao diện web (chưa)
  • Không có khả năng lưu trữ - Cuộc trò chuyện không lưu giữa các phiên

Những hạn chế này giữ cho mã đơn giản trong khi vẫn cung cấp chức năng cốt lõi.

Điều gì Tiếp theo?

Bài viết tiếp theo của chúng ta sẽ đi sâu vào việc thực thi đa công cụ, phần 7 trong chuỗi "Từ con số đến Đại lý AI: Hành trình của tôi vào Ứng dụng Thông minh dựa trên Java"! Chúng ta sẽ khám phá cách xây dựng một hệ thống điều phối các quy trình phức tạp, xử lý các yêu cầu thực tế của người dùng như "Lấy thời tiết ở Tokyo và lưu vào tệp" hoặc "Kiểm tra giá trên ba trang web và cho tôi biết giá rẻ nhất" bằng cách phối hợp nhiều công cụ một cách liền mạch. Hãy theo dõi!

Mã nguồn hoàn chỉnh có sẵn trong kho GitHub của chúng tôi.


Đây là phần 6 trong chuỗi bài viết về xây dựng các đại lý AI bằng Java với Giao thức Ngữ cảnh Mô hình. Tiếp theo: xử lý lỗi mạnh mẽ và các mẫu đối thoại nâng cao!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào