AI Services是什么
AI Services 的设计灵感来源于 Spring Data JPA 和 Retrofit 等框架,采用声明式接口定义所需的 API,然后由框架自动生成实现该接口的代理对象。这种方法隐藏了与 LLM 交互的复杂性,提供了简单直观的 API。
AI Services 主要处理以下常见操作:
- 格式化输入以发送给 LLM
- 解析 LLM 的输出
同时还支持更高级的功能:
- 聊天记忆管理
- 工具调用(Function Calling)
- 检索增强生成(RAG)
基本使用示例
LangChain4j是 Java 生态系统中的一个流行框架,它提供了两种抽象级别:低级 API 和高级 API。其中,AI Services 是一种专为 Java 量身定制的高级 API 解决方案。以下是 LangChain4j AI Services 的最简单示例:
复制// 定义接口 interface Assistant { String chat(String userMessage); } // 创建低级组件 ChatLanguageModel model = OpenAiChatModel.builder() .apiKey(System.getenv("OPENAI_API_KEY")) .modelName("gpt-4o-mini") .build(); // 创建AI Service实例 Assistant assistant = AiServices.create(Assistant.class, model); // 使用AI Service String answer = assistant.chat("Hello"); System.out.println(answer); // Hello, how can I help you?
使用系统消息和用户消息
lanchain4j 提供了@SystemMessage 和@UserMessage 注解来自定义提示:
复制// 使用系统消息 interface Friend { @SystemMessage("You are a good friend of mine. Answer using slang.") String chat(String userMessage); } // 使用用户消息模板 interface Advisor { @UserMessage("You are a professional advisor. Please answer this question: {{it}}") String getAdvice(String question); }
基于 Spring AI 的自定义注解实现
虽然 lanchain4j 提供了全面的解决方案,但对于已经使用 Spring AI 的项目,我们可以创建一个轻量级的自定义注解来简化集成过程。
所需依赖
首先,我们需要添加以下依赖到项目中:
复制<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency>
配置 ChatClient
接下来,我们需要使用 OllamaChatModel 配置 ChatClient。在 Spring 配置类中添加以下 Bean 定义:
复制@Bean public ChatClient chatClient(ChatModel chatModel) { return ChatClient.builder(chatModel) .defaultSystem("你是一个有用的AI助手,能够回答用户的问题并提供帮助。") .build(); }
创建自定义注解
现在,让我们创建@AiPrompt注解,它将用于标记需要 AI 处理的方法:
复制@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AiPrompt { String systemMessage() default ""; }
实现 AOP 切面
接下来,我们需要实现一个 AOP 切面来拦截带有@AiPrompt注解的方法调用:
复制@Aspect @Component @RequiredArgsConstructor publicclass AiPromptAspect { privatefinal ChatClient deepSeekChatClient; @Around("@annotation(aiPrompt)") public Object processAiPrompt(ProceedingJoinPoint joinPoint, AiPrompt aiPrompt) throws Throwable { // 获取方法参数 Object[] args = joinPoint.getArgs(); if (args.length == 0) { return joinPoint.proceed(); } // 假设第一个参数是用户的输入消息 String userMessage = args[0].toString(); // 创建ChatClient请求 ChatClient.ChatClientRequestSpec requestSpec = deepSeekChatClient.prompt(); // 如果注解中指定了系统消息,则使用它 if (!aiPrompt.systemMessage().isEmpty()) { requestSpec = requestSpec.system(aiPrompt.systemMessage()); } return requestSpec .user(userMessage) .call() .content(); } }
使用示例
现在,我们可以在服务类中使用@AiPrompt注解:
复制@Service @RequiredArgsConstructor public class ChatService { @AiPrompt(systemMessage = "你是一个专业的Java开发顾问,擅长解答Spring框架相关问题。") public String getJavaAdvice(String question) { return null; // 这个返回值会被AOP切面中的返回值覆盖 } }
控制器示例
最后,我们可以在controller中使用这个服务:
复制@RestController @RequestMapping("/api") @RequiredArgsConstructor public class ChatController { private final ChatService chatService; @PostMapping("/chat") public String getJavaAdvice(@RequestBody String question) { return chatService.getJavaAdvice(question); } }
总结
参考 lanchain4j的高级 API 设计形式,基于 Spring AI 自定义注解实现的 AI services 可以有效地实现提示词模板的集中管理和复用,通过 AOP 机制自动处理 AI 接口的调用逻辑,显著提升开发效率。 这种模式不仅降低了与 AI 服务交互的代码复杂度,还通过标准化注解配置实现了以下优势:
- 提示词工程的可维护性提升;
- 业务代码与 AI 基础设施解耦;
- 可以无缝集成 Spring 生态的其他能力,比如 Spring Cache 实现 AI 注解式缓存