Java使用Spring AI的10個實用技巧分享
引言
在當今的軟件開發(fā)領域,人工智能的集成已經(jīng)成為提升應用功能和用戶體驗的重要手段。對于 Java 開發(fā)者而言,Spring AI 提供了一套強大且便捷的工具,使得在 Java 項目中集成 AI 功能變得更加輕松。本文將深入探討 Java 使用 Spring AI 的 10 個實用技巧,幫助開發(fā)者充分發(fā)揮 Spring AI 的潛力,打造出更加智能、高效的應用程序。
技巧 1:使用 @EnableSpringAI 注解快速啟動
在 Spring Boot 應用中,快速啟動 Spring AI 的配置可以通過@EnableSpringAI注解輕松實現(xiàn)。這個注解會自動觸發(fā)一系列 AI 相關的配置,極大地簡化了我們的工作。
首先,在項目的依賴中引入 Spring AI 相關的庫。如果使用 Maven,在pom.xml文件中添加如下依賴:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-deepseek</artifactId>
<version>1.0.0</version>
</dependency>
然后,在 Spring Boot 的主應用類上添加@EnableSpringAI注解:
@SpringBootApplication
@EnableSpringAI
public class MySpringAiApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringAiApplication.class, args);
}
}
通過上述簡單操作,Spring 會自動掃描并配置 AI 相關的 Bean,我們無需手動編寫大量繁瑣的配置代碼,即可快速開啟 Spring AI 之旅。
技巧 2:通過 AiClient 接口注入不同提供商的客戶端
Spring AI 的AiClient接口是一個強大的抽象,它允許我們輕松地集成不同的 AI 服務提供商,如 DeepSeek 等。
在application.yml中添加 DeepSeek 客戶端的配置:
spring:
ai:
deepseek:
api-key: your_deepseek_api_key
base-url: https://api.deepseek.com/v1
然后,創(chuàng)建一個配置類來注入DeepSeekClient:
@Configuration
public class AiClientConfig {
@Bean
public DeepSeekClient deepSeekClient(DeepSeekClientProperties properties) {
return new DeepSeekClient(properties.getApiKey());
}
}
這樣,在其他組件中,我們就可以通過依賴注入的方式使用DeepSeekClient了:
@Service
public class MyAiService {
private final DeepSeekClient deepSeekClient;
public MyAiService(DeepSeekClient deepSeekClient) {
this.deepSeekClient = deepSeekClient;
}
public String generateText(String prompt) {
// 使用DeepSeekClient進行文本生成
return deepSeekClient.generate(prompt).getGeneratedText();
}
}
通過這種方式,我們可以根據(jù)項目需求輕松切換不同的 AI 服務提供商,而無需對業(yè)務邏輯進行大規(guī)模修改。
技巧 3:使用 PromptTemplate 分離業(yè)務邏輯和提示詞
在使用 AI 進行文本生成等任務時,提示詞的管理至關重要。PromptTemplate允許我們將業(yè)務邏輯與提示詞分離,提高代碼的可維護性和復用性。
假設我們有一個簡單的文本總結需求,定義一個提示詞模板:
public class SummaryService {
private static final String SUMMARY_TEMPLATE = "請總結以下內容:{text}";
public String summarizeText(String text) {
PromptTemplate promptTemplate = new PromptTemplate(SUMMARY_TEMPLATE);
// 使用模板生成具體的提示詞
String prompt = promptTemplate.render("text", text);
// 這里假設已經(jīng)有一個AiClient實例用于生成文本
String summary = aiClient.generate(prompt).getGeneratedText();
return summary;
}
}
在上述代碼中,SUMMARY_TEMPLATE定義了提示詞的結構,{text}是一個占位符。通過render方法,我們將實際的文本內容填充到占位符中,生成最終的提示詞。這樣,當我們需要修改提示詞的格式或邏輯時,只需在SUMMARY_TEMPLATE中進行調整,而不會影響到業(yè)務邏輯代碼。
技巧 4:實現(xiàn) MessageConverter 處理復雜數(shù)據(jù)格式
在實際應用中,我們可能需要處理各種復雜的數(shù)據(jù)格式,如 JSON、XML 等。Spring AI 的MessageConverter接口可以幫助我們實現(xiàn)數(shù)據(jù)格式的轉換,以便更好地與 AI 模型交互。
以 JSON 格式為例,我們定義一個自定義的MessageConverter來將 JSON 字符串轉換為 AI 模型所需的Message對象:
@Component
public class JsonMessageConverter implements MessageConverter {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public Message toMessage(String json) {
try {
// 假設JSON結構中有一個"content"字段表示用戶輸入
JsonInput jsonInput = objectMapper.readValue(json, JsonInput.class);
return new UserMessage(jsonInput.getContent());
} catch (Exception e) {
throw new RuntimeException("Failed to convert JSON to Message", e);
}
}
@Override
public String fromMessage(Message message) {
try {
JsonOutput jsonOutput = new JsonOutput(message.getContent());
return objectMapper.writeValueAsString(jsonOutput);
} catch (Exception e) {
throw new RuntimeException("Failed to convert Message to JSON", e);
}
}
private static class JsonInput {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
private static class JsonOutput {
private String result;
public JsonOutput(String result) {
this.result = result;
}
public String getResult() {
return result;
}
}
}
在上述代碼中,toMessage方法將 JSON 字符串解析為UserMessage對象,fromMessage方法則將Message對象轉換回 JSON 格式。這樣,我們可以在與 AI 模型交互時,方便地處理 JSON 數(shù)據(jù),確保數(shù)據(jù)格式的兼容性。
技巧 5:集成 Spring Security 保護 AI 接口
當我們將 AI 功能暴露為接口供外部使用時,安全保護是必不可少的。Spring Security 可以幫助我們輕松實現(xiàn)對 AI 接口的安全防護。
首先,添加 Spring Security 的依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
然后,創(chuàng)建一個 Spring Security 配置類:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/ai/**").authenticated()
.anyRequest().permitAll()
.and()
.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
return new JwtAuthenticationFilter();
}
}
在上述配置中,我們禁用了 CSRF 保護(因為在無狀態(tài)的 API 場景中通常不需要),設置了會話創(chuàng)建策略為無狀態(tài),并且配置了對/ai/**路徑下的請求進行身份驗證。JwtAuthenticationFilter是一個自定義的過濾器,用于處理 JWT 認證,具體實現(xiàn)如下:
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private static final String HEADER_STRING = "Authorization";
private static final String TOKEN_PREFIX = "Bearer ";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String header = request.getHeader(HEADER_STRING);
if (header == null ||!header.startsWith(TOKEN_PREFIX)) {
filterChain.doFilter(request, response);
return;
}
String token = header.replace(TOKEN_PREFIX, "");
Claims claims = Jwts.parser().setSigningKey("your_secret_key").parseClaimsJws(token).getBody();
String username = claims.getSubject();
List<String> roles = (List<String>) claims.get("roles");
List<SimpleGrantedAuthority> authorities = roles.stream()
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
filterChain.doFilter(request, response);
}
}
通過上述配置和過濾器,我們實現(xiàn)了基于 JWT 的身份驗證,確保只有經(jīng)過授權的用戶才能訪問 AI 接口,保障了系統(tǒng)的安全性。
技巧 6:使用 AiFunction 注解暴露 Java 方法給 AI 模型
AiFunction注解是 Spring AI 提供的一個強大功能,它允許我們將 Java 方法暴露為 AI 模型可以調用的函數(shù)。這在很多場景下非常有用,比如讓 AI 模型根據(jù)業(yè)務需求調用特定的 Java 邏輯。
假設我們有一個計算商品折扣價格的 Java 方法,我們可以使用AiFunction注解將其暴露:
@Component
public class DiscountService {
@AiFunction(
name = "calculateDiscountPrice",
description = "計算商品的折扣價格,輸入商品原價和折扣率,返回折扣后的價格"
)
public double calculateDiscountPrice(double originalPrice, double discountRate) {
return originalPrice * (1 - discountRate);
}
}
在上述代碼中,@AiFunction注解指定了函數(shù)的名稱和描述。這樣,AI 模型在需要計算折扣價格時,就可以通過調用calculateDiscountPrice函數(shù)來實現(xiàn)。
技巧 7:配置 AiClientProperties 調整連接超時和重試策略
為了優(yōu)化 AI 客戶端與服務提供商之間的交互性能,我們可以通過配置AiClientProperties來調整連接超時和重試策略。
在application.yml中添加如下配置:
spring:
ai:
deepseek:
client:
connection-timeout: 5000
read-timeout: 10000
max-retries: 3
上述配置中,spring.ai.deepseek.client.connection-timeout設置了連接超時時間為 5 秒,spring.ai.deepseek.client.read-timeout設置了讀取超時時間為 10 秒,spring.ai.deepseek.client.max-retries設置了最大重試次數(shù)為 3 次。
在代碼中,我們可以通過注入DeepSeekClientProperties來獲取這些配置并應用到DeepSeekClient中:
@Configuration
public class DeepSeekClientConfig {
@Bean
public DeepSeekClient deepSeekClient(DeepSeekClientProperties properties) {
DeepSeekClient client = new DeepSeekClient(properties.getApiKey());
client.setConnectionTimeout(properties.getConnectionTimeout());
client.setReadTimeout(properties.getReadTimeout());
client.setMaxRetries(properties.getMaxRetries());
return client;
}
}
通過合理配置連接超時和重試策略,可以提高 AI 客戶端在網(wǎng)絡不穩(wěn)定等情況下的可靠性和性能。
技巧 8:使用 ReactiveAiClient 實現(xiàn)非阻塞請求處理
在高并發(fā)的應用場景中,使用響應式編程模型可以顯著提高系統(tǒng)的性能和資源利用率。Spring AI 提供的ReactiveAiClient接口允許我們以非阻塞的方式處理 AI 請求。
假設我們有一個需要調用 AI 模型生成文本的服務,使用ReactiveAiClient可以這樣實現(xiàn):
@Service
public class ReactiveAiTextGenerationService {
private final ReactiveDeepSeekClient reactiveDeepSeekClient;
public ReactiveAiTextGenerationService(ReactiveDeepSeekClient reactiveDeepSeekClient) {
this.reactiveDeepSeekClient = reactiveDeepSeekClient;
}
public Mono<String> generateText(String promptText) {
Prompt prompt = new Prompt(new UserMessage(promptText));
return reactiveDeepSeekClient.generate(prompt)
.map(response -> response.getGeneratedText());
}
}
在上述代碼中,generateText方法返回一個Mono<String>,表示一個異步的文本生成操作。通過這種方式,我們可以在不阻塞線程的情況下處理大量的 AI 請求,提高系統(tǒng)的吞吐量和響應速度。
技巧 9:通過 AiMessageHistory 維護多輪對話上下文
在涉及多輪對話的場景中,如聊天機器人,維護對話上下文非常重要。Spring AI 的AiMessageHistory可以幫助我們輕松實現(xiàn)這一點。
創(chuàng)建一個服務類來管理對話歷史:
@Service
public class ChatService {
private final AiMessageHistory messageHistory;
private final DeepSeekClient deepSeekClient;
public ChatService(DeepSeekClient deepSeekClient, AiMessageHistory messageHistory) {
this.deepSeekClient = deepSeekClient;
this.messageHistory = messageHistory;
}
public String chat(String userInput) {
UserMessage userMessage = new UserMessage(userInput);
messageHistory.addMessage(userMessage);
String response = deepSeekClient.generate(messageHistory.getMessages()).getGeneratedText();
AiMessage aiResponse = new AiMessage(response);
messageHistory.addMessage(aiResponse);
return response;
}
}
在上述代碼中,每次用戶輸入消息時,我們將其添加到messageHistory中,然后使用messageHistory中的所有消息與 AI 模型進行交互,獲取 AI 的響應后,再將響應添加到messageHistory中。這樣,messageHistory始終維護著完整的對話上下文,使得 AI 模型能夠根據(jù)之前的對話內容進行更準確的回復。
技巧 10:自定義 AiResponseHandler 處理大文本的分段生成
在處理大文本生成時,一次性獲取全部文本可能會導致內存問題或長時間等待。Spring AI 允許我們自定義AiResponseHandler來處理流式響應,實現(xiàn)大文本的分段生成。
首先,定義一個自定義的AiResponseHandler:
public class CustomAiResponseHandler implements AiResponseHandler {
private final List<String> partialTexts = new ArrayList<>();
@Override
public void handleResponse(AiResponse response) {
String partialText = response.getGeneratedText();
partialTexts.add(partialText);
System.out.println("接收到分段文本: " + partialText);
}
public String getFullText() {
return String.join("", partialTexts);
}
}
在實際使用時,我們可以將自定義的AiResponseHandler與ReactiveAiClient結合,實現(xiàn)響應式的流式文本生成處理:
@Service
public class StreamingTextGenerationService {
private final ReactiveDeepSeekClient reactiveDeepSeekClient;
public StreamingTextGenerationService(ReactiveDeepSeekClient reactiveDeepSeekClient) {
this.reactiveDeepSeekClient = reactiveDeepSeekClient;
}
public Mono<Void> generateStreamingText(String promptText, CustomAiResponseHandler handler) {
Prompt prompt = new Prompt(new UserMessage(promptText));
return reactiveDeepSeekClient.generateStreaming(prompt)
.doOnNext(handler::handleResponse)
.then();
}
}
在generateStreamingText方法中,reactiveDeepSeekClient.generateStreaming發(fā)起流式文本生成請求,doOnNext操作會在每次接收到分段響應時調用CustomAiResponseHandler的handleResponse方法,最后通過then操作返回一個表示操作完成的Mono<Void>。
通過這種方式,我們可以有效處理大文本生成場景,避免一次性加載大量文本導致的內存壓力,同時還能在文本生成過程中及時展示內容,提升用戶體驗。
總結
本文詳細介紹了 Java 使用 Spring AI 的 10 個實用技巧,從項目初始化到復雜場景優(yōu)化均有覆蓋。這些技巧涵蓋了 Spring AI 應用開發(fā)的全流程,無論是初涉 AI 開發(fā)的新手,還是尋求技術突破的資深開發(fā)者,都能從中獲取實用的技術方案。通過合理運用這些技巧,Java 開發(fā)者可以更高效地將 AI 能力融入項目,打造出功能強大、體驗出色的智能應用
以上就是Java使用Spring AI的10個實用技巧分享的詳細內容,更多關于Java使用Spring AI的資料請關注腳本之家其它相關文章!
相關文章
Jenkins Maven pom jar打包未拉取最新包解決辦法
包版本號未變更新后,jenkins打包不會拉取最新包,本文主要介紹了Jenkins Maven pom jar打包未拉取最新包解決辦法,具有一定的參考價值,感興趣的可以了解一下2024-02-02
MyBatis入門實例教程之創(chuàng)建一個簡單的程序
這篇文章主要介紹了MyBatis入門創(chuàng)建一個簡單的程序,在?MySQL?中創(chuàng)建數(shù)據(jù)庫?mybatisdemo,編碼為?utf8,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2022-02-02
Mybatis以main方法形式調用dao層執(zhí)行代碼實例
這篇文章主要介紹了Mybatis以main方法形式調用dao層執(zhí)行代碼實例,MyBatis 是一款優(yōu)秀的持久層框架,MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數(shù)和獲取結果集的工作,需要的朋友可以參考下2023-08-08

