Spring AI là một module của Spring giúp chúng ta dễ dàng làm việc với các ứng dụng có sử dụng AI, có tích hợp sử dụng các AI provider như OpenAI, Azure OpenAI, Google Gemini, … Trong bài viết này, mình sẽ giới thiệu với các bạn các kiến thức cơ bản về Spring AI để các bạn có thể sử dụng nó trong các ứng dụng có tích hợp sử dụng các AI provider các bạn nhé!
Đầu tiên, mình sẽ tạo mới một Maven project để làm ví dụ:
Mình sẽ làm một ứng dụng nhỏ tích hợp với OpenAI để truy vấn thông tin nên mình sẽ khai báo sử dụng Spring AI cho OpenAI dependency như sau:
1 2 3 4 5 |
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai</artifactId> <version>1.0.0-M5</version> </dependency> |
Hiện tại spring-ai-openai artifact chưa available trên official Remote Maven Repository, chỉ trên Spring Milestones Repository nên các bạn cần khai báo thêm thông tin của Spring Milestones Repository để có thể sử dụng nó nhé:
1 2 3 4 5 6 7 8 9 10 |
<repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> |
Các khái niệm AI cơ bản
Trước khi đi vào implement ví dụ, có một số khái niệm về AI mà các bạn cần nắm như sau:
Model là các thuật toán để xử lý thông tin request của người dùng và generate output phù hợp với request. Các thuật toán này sẽ sử dụng một số lượng lớn dữ liệu được input trước đó để đưa ra các dự đoán, chữ, hình ảnh và các output khác.
Prompts có thể nói nôm na là các input request từ người dùng, thông thường có thể là text input, để AI model dựa vào đó để generate output.
Prompt Templates là các template dùng để tạo các prompt. Chúng ta sẽ cần phải thay thế các placeholder được định nghĩa trong template bằng các giá trị mà chúng ta muốn để tạo được prompt từ các giá trị này.
Embeddings là các đối tượng sẽ transform các prompt của user thành các đối tượng vector dưới dạng các chữ số cho phép các AI model có thể sử dụng để process request.
Tokens là đơn vị ngôn ngữ cơ bản mà AI model sử dụng để process các prompt. Lúc input, thì AI model sẽ convert các từ ngữ qua các tokens, lúc output thì AI model sẽ convert tokens qua các từ ngữ.
Hiểu các khái niệm cơ bản trên, các bạn sẽ hình dung ở mức high level cách mà một ứng dụng AI hoạt động sẽ như thế nào đó các bạn!
Spring AI cơ bản
Để integrate với các AI provider, Spring AI định nghĩa một interface tên là Model với ModelRequest và ModelResponse:
1 2 3 |
public interface Model<TReq extends ModelRequest<?>, TRes extends ModelResponse<?>> { TRes call(TReq request); } |
Có 6 sub-interface từ interface Model là:
- ChatModel
- ImageModel
- DocumentEmbeddingModel
- SpeechModel
- ModerationModel
- và EmbeddingModel
Tương ứng với từng AI provider thì sẽ có implementation riêng các bạn nhé!
Cho OpenAI, các implementation cho 5 interface ChatModel, ImageModel, SpeechModel, ModerationModel và EmbeddingModel lần lượt là OpenAiChatModel, OpenAiImageModel, OpenAiAudioSpeechModel, OpenAiModerationModel, OpenAiEmbeddingModel. Ngoài ra thì còn có một implementation khác của OpenAI cho interface Model là OpenAiAudioTranscriptionModel nha các bạn:
Cho ví dụ của mình, mình sẽ sử dụng class ChatModel để làm việc với OpenAI các bạn nhé!
Hiện thực ví dụ
Để integrate với OpenAI, trước tiên, các bạn cần tạo mới một API key trong OpenAI platform bằng cách đi đến trang https://platform.openai.com/api-keys và click vào nút “Create new secret key” như sau:
API key này dùng để authenticate với OpenAI API đó các bạn! Hãy lưu thông tin API key này ở đâu đó để có thể sử dụng lại sau này các bạn nhé!
Để cấu hình thông tin OpenAI với Spring AI, các bạn có thể sử dụng class OpenAiApi.
Có 4 overloading constructors để khởi tạo đối tượng của class OpenAiApi này với thông tin bắt buộc mà chúng ta cần phải cấu hình là về API key:
- OpenAiApi(String baseUrl, String apiKey, MultiValueMap<String, String> headers, String completionsPath, String embeddingsPath, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder, ResponseErrorHandler responseErrorHandler)
- OpenAiApi(String baseUrl, String apiKey, String completionsPath, String embeddingsPath, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder, ResponseErrorHandler responseErrorHandler)
- OpenAiApi(String baseUrl, String apiKey, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder, ResponseErrorHandler responseErrorHandler)
- OpenAiApi(String baseUrl, String apiKey, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder)
- OpenAiApi(String baseUrl, String apiKey)
- OpenAiApi(String apiKey)
Constructor đầu tiên sẽ cho phép chúng ta cấu hình về:
- baseUrl của OpenAI để truy vấn thông tin,
- apiKey là API key mà chúng ta vừa tạo ở trên,
- headers là thông tin các headers mà các bạn cần truyền trong request tới OpenAI API,
- completionsPath
- embeddingsPath
- restClientBuilder, webClientBuilder và responseErrorHandler cho phép chúng ta định nghĩa các cấu hình liên quan đến request tới OpenAI và handle lỗi lúc nhận được response từ OpenAI.
Các constructor sau sẽ sử dụng các cấu hình mặc định của Spring với baseUrl của OpenAI API mặc định là “https://api.openai.com” nha các bạn!
Các bạn có thể sử dụng các cấu hình mặc định và chỉ định nghĩa thông tin về API key sử dụng constructor cuối như sau:
1 2 3 4 5 |
@Bean OpenAiApi openAiApi() { return new OpenAiApi( "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"); } |
Và khởi tạo bean của class ChatModel từ đối tượng của class OpenAiApi như sau:
1 2 3 4 |
@Bean ChatModel chatModel(OpenAiApi openAiApi) { return new OpenAiChatModel(openAiApi); } |
Các bạn có thể chọn OpenAI Model mà các bạn muốn sử dụng bằng cách khai báo thêm một tham số trong phần khởi tạo bean cho class OpenAiChatModel như sau:
1 2 3 4 5 |
@Bean ChatModel chatModel(OpenAiApi openAiApi) { return new OpenAiChatModel(openAiApi, OpenAiChatOptions.builder().model(OpenAiApi.ChatModel.O1_MINI).build()); } |
Ở đây, mình đang khai báo sử dụng model “01-mini”. Mặc định thì OpenAiChatModel sẽ sử dụng model “gpt-4o” nhé các bạn!
Với khai báo trên, Spring sẽ tự động khởi tạo đối tượng OpenAiApi, sau đó là đối tượng ChatClient trong Spring container, chúng ta chỉ cần ingest vào và sử dụng mà thôi:
1 2 3 4 |
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( AppConfiguration.class); ChatModel chatModel = context.getBean(ChatModel.class); |
Bây giờ thì chúng ta có thể sử dụng class ChatModel để truy vấn thông tin từ OpenAI rồi đó các bạn.
Ví dụ của mình như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.huongdanjava.springai; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Application { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( AppConfiguration.class); ChatModel chatModel = context.getBean(ChatModel.class); ChatResponse chatResponse = chatModel.call(new Prompt("Do you know about Huong Dan Java website?")); System.out.println(chatResponse.getResult()); } } |
Các bạn hãy thử kiểm tra kết quả như thế nào nhé! Của mình hiện tại đã hết lượt sử dụng free nên khi chạy, mình đang bị lỗi sau:
1 2 3 4 5 6 7 8 |
org.springframework.ai.retry.NonTransientAiException: 429 - { "error": { "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", "type": "insufficient_quota", "param": null, "code": "insufficient_quota" } } |