掘金 人工智能 06月10日 10:39
Java 使用 Spring AI 的 10 个实用技巧
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文为 Java 开发者提供了使用 Spring AI 的 10 个实用技巧,涵盖了从快速启动、集成 AI 客户端、Prompt 模板使用,到数据格式处理、安全保护、函数调用、性能优化和多轮对话管理等多个方面,帮助开发者构建更智能、高效的应用程序。 通过这些技巧,开发者可以充分利用 Spring AI 的强大功能,简化 AI 集成流程,提升用户体验。

🚀 通过`@EnableSpringAI`注解,可以快速启动 Spring AI,简化配置流程,无需手动编写繁琐的配置代码,方便快捷地开启 Spring AI 之旅。

💡 利用 `AiClient` 接口,可以轻松集成不同的 AI 服务提供商,例如 DeepSeek,通过配置 API 密钥和基础 URL,实现灵活切换,而无需大规模修改业务逻辑。

📝 使用 `PromptTemplate` 将业务逻辑与提示词分离,提高代码可维护性和复用性。通过定义模板和占位符,动态生成提示词,方便修改提示词格式和逻辑,而不影响业务代码。

⚙️ 借助 `MessageConverter` 接口,可以处理复杂数据格式,比如 JSON。通过自定义 `MessageConverter`,实现数据格式转换,确保与 AI 模型交互时的数据兼容性。

🛡️ 集成 Spring Security 可以保护 AI 接口。通过添加 Spring Security 依赖,配置安全策略,并使用 JWT 认证,确保只有授权用户才能访问 AI 接口,保障系统安全。

🔗 利用 `@AiFunction` 注解,可以将 Java 方法暴露给 AI 模型,使其能够调用 Java 逻辑。这允许 AI 模型根据业务需求执行特定操作,例如计算折扣价格,实现更强大的功能。

⏱️ 通过配置 `AiClientProperties`,可以调整连接超时和重试策略,优化 AI 客户端与服务提供商之间的交互性能。合理配置这些参数,提高在网络不稳定等情况下的可靠性和性能。

🔄 使用 `ReactiveAiClient`,可以实现非阻塞请求处理,提高系统性能和资源利用率。这在处理大量 AI 请求时非常有效,提升系统的吞吐量和响应速度。

💬 通过 `AiMessageHistory`,可以维护多轮对话上下文,支持聊天机器人等场景。这使得 AI 模型能够记住之前的对话内容,提供更连贯、自然的交互体验。

引言

在当今的软件开发领域,人工智能的集成已经成为提升应用功能和用户体验的重要手段。对于 Java 开发者而言,Spring AI 提供了一套强大且便捷的工具,使得在 Java 项目中集成 AI 功能变得更加轻松。本文将深入探讨 Java 使用 Spring AI 的 10 个实用技巧,帮助开发者充分发挥 Spring AI 的潜力,打造出更加智能、高效的应用程序。

技巧 1:使用 @EnableSpringAI 注解快速启动

在 Spring Boot 应用中,快速启动 Spring AI 的配置可以通过@EnableSpringAI注解轻松实现。这个注解会自动触发一系列 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@EnableSpringAIpublic 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

然后,创建一个配置类来注入DeepSeekClient

@Configurationpublic class AiClientConfig {    @Bean    public DeepSeekClient deepSeekClient(DeepSeekClientProperties properties) {        return new DeepSeekClient(properties.getApiKey());    }}

这样,在其他组件中,我们就可以通过依赖注入的方式使用DeepSeekClient了:

@Servicepublic class MyAiService {    private final DeepSeekClient deepSeekClient;    public MyAiService(DeepSeekClient deepSeekClient) {        this.deepSeekClient = deepSeekClient;    }    public String generateText(String prompt) {        // 使用DeepSeekClient进行文本生成        return deepSeekClient.generate(prompt).getGeneratedText();    }}

通过这种方式,我们可以根据项目需求轻松切换不同的 AI 服务提供商,而无需对业务逻辑进行大规模修改。

技巧 3:使用 PromptTemplate 分离业务逻辑和提示词

在使用 AI 进行文本生成等任务时,提示词的管理至关重要。PromptTemplate允许我们将业务逻辑与提示词分离,提高代码的可维护性和复用性。

假设我们有一个简单的文本总结需求,定义一个提示词模板:

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);        // 这里假设已经有一个AiClient实例用于生成文本        String summary = aiClient.generate(prompt).getGeneratedText();        return summary;    }}

在上述代码中,SUMMARY_TEMPLATE定义了提示词的结构,{text}是一个占位符。通过render方法,我们将实际的文本内容填充到占位符中,生成最终的提示词。这样,当我们需要修改提示词的格式或逻辑时,只需在SUMMARY_TEMPLATE中进行调整,而不会影响到业务逻辑代码。

技巧 4:实现 MessageConverter 处理复杂数据格式

在实际应用中,我们可能需要处理各种复杂的数据格式,如 JSON、XML 等。Spring AI 的MessageConverter接口可以帮助我们实现数据格式的转换,以便更好地与 AI 模型交互。

以 JSON 格式为例,我们定义一个自定义的MessageConverter来将 JSON 字符串转换为 AI 模型所需的Message对象:

@Componentpublic 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 数据,确保数据格式的兼容性。

技巧 5:集成 Spring Security 保护 AI 接口

当我们将 AI 功能暴露为接口供外部使用时,安全保护是必不可少的。Spring Security 可以帮助我们轻松实现对 AI 接口的安全防护。

首先,添加 Spring Security 的依赖:

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-security</artifactId></dependency>

然后,创建一个 Spring Security 配置类:

@Configuration@EnableWebSecuritypublic 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 保护(因为在无状态的 API 场景中通常不需要),设置了会话创建策略为无状态,并且配置了对/ai/**路径下的请求进行身份验证。JwtAuthenticationFilter是一个自定义的过滤器,用于处理 JWT 认证,具体实现如下:

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);    }}

通过上述配置和过滤器,我们实现了基于 JWT 的身份验证,确保只有经过授权的用户才能访问 AI 接口,保障了系统的安全性。

技巧 6:使用 AiFunction 注解暴露 Java 方法给 AI 模型

AiFunction注解是 Spring AI 提供的一个强大功能,它允许我们将 Java 方法暴露为 AI 模型可以调用的函数。这在很多场景下非常有用,比如让 AI 模型根据业务需求调用特定的 Java 逻辑。

假设我们有一个计算商品折扣价格的 Java 方法,我们可以使用AiFunction注解将其暴露:

@Componentpublic class DiscountService {    @AiFunction(        name = "calculateDiscountPrice",        description = "计算商品的折扣价格,输入商品原价和折扣率,返回折扣后的价格"    )    public double calculateDiscountPrice(double originalPrice, double discountRate) {        return originalPrice * (1 - discountRate);    }}

在上述代码中,@AiFunction注解指定了函数的名称和描述。这样,AI 模型在需要计算折扣价格时,就可以通过调用calculateDiscountPrice函数来实现。

技巧 7:配置 AiClientProperties 调整连接超时和重试策略

为了优化 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设置了最大重试次数为 3 次。

在代码中,我们可以通过注入DeepSeekClientProperties来获取这些配置并应用到DeepSeekClient中:

@Configurationpublic 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 客户端在网络不稳定等情况下的可靠性和性能。

技巧 8:使用 ReactiveAiClient 实现非阻塞请求处理

在高并发的应用场景中,使用响应式编程模型可以显著提高系统的性能和资源利用率。Spring AI 提供的ReactiveAiClient接口允许我们以非阻塞的方式处理 AI 请求。

假设我们有一个需要调用 AI 模型生成文本的服务,使用ReactiveAiClient可以这样实现:

@Servicepublic 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 请求,提高系统的吞吐量和响应速度。

技巧 9:通过 AiMessageHistory 维护多轮对话上下文

在涉及多轮对话的场景中,如聊天机器人,维护对话上下文非常重要。Spring AI 的AiMessageHistory可以帮助我们轻松实现这一点。

创建一个服务类来管理对话历史:

@Servicepublic 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 模型能够根据之前的对话内容进行更准确的回复。

技巧 10:自定义 AiResponseHandler 处理大文本的分段生成

在处理大文本生成时,一次性获取全部文本可能会导致内存问题或长时间等待。Spring AI 允许我们自定义AiResponseHandler来处理流式响应,实现大文本的分段生成。

首先,定义一个自定义的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);    }}

在实际使用时,我们可以将自定义的AiResponseHandlerReactiveAiClient结合,实现响应式的流式文本生成处理:

@Servicepublic 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发起流式文本生成请求,doOnNext操作会在每次接收到分段响应时调用CustomAiResponseHandlerhandleResponse方法,最后通过then操作返回一个表示操作完成的Mono<Void>

通过这种方式,我们可以有效处理大文本生成场景,避免一次性加载大量文本导致的内存压力,同时还能在文本生成过程中及时展示内容,提升用户体验。

总结

本文详细介绍了 Java 使用 Spring AI 的 10 个实用技巧,从项目初始化到复杂场景优化均有覆盖。这些技巧涵盖了 Spring AI 应用开发的全流程,无论是初涉 AI 开发的新手,还是寻求技术突破的资深开发者,都能从中获取实用的技术方案。通过合理运用这些技巧,Java 开发者可以更高效地将 AI 能力融入项目,打造出功能强大、体验出色的智能应用

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Spring AI Java 人工智能 AI开发
相关文章