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:
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ĩ:
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:
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ế:
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):
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):
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):
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:
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:
export GROQ_API_KEY=your_key_here
Cài đặt các máy chủ MCP:
npm install -g @modelcontextprotocol/server-weather
npm install -g @modelcontextprotocol/server-filesystem
Chạy trò chuyện:
# 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!