> ## Documentation Index
> Fetch the complete documentation index at: https://blog.pig4cloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 【实战干货】Spring AI这样玩才高级！注解式AI服务开发，这些技巧 GitHub 都找不到

## AI Services

[LangChain4j](https://docs.langchain4j.dev/tutorials/ai-services)是Java生态系统中的一个流行框架，它提供了两种抽象级别：低级API和高级API。其中，AI Services是一种专为Java量身定制的高级API解决方案。

### AI Services的核心理念

AI Services的设计灵感来源于Spring Data JPA和Retrofit等框架，采用声明式接口定义所需的API，然后由框架自动生成实现该接口的代理对象。这种方法隐藏了与LLM交互的复杂性，提供了简单直观的API。

AI Services主要处理以下常见操作：

* 格式化输入以发送给LLM
* 解析LLM的输出

同时还支持更高级的功能：

* 聊天记忆管理
* 工具调用(Function Calling)
* 检索增强生成(RAG)

### 基本使用示例

以下是LangChain4j AI Services的最简单示例：

```java theme={null}
// 定义接口
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?
```

### 使用系统消息和用户消息

LangChain4j提供了`@SystemMessage`和`@UserMessage`注解来自定义提示：

```java theme={null}
// 使用系统消息
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的自定义注解实现

虽然LangChain4j提供了全面的解决方案，但对于已经使用Spring AI的项目，我们可以创建一个轻量级的自定义注解来简化集成过程。

### 所需依赖

首先，我们需要添加以下依赖到项目中：

```xml theme={null}
<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定义：

```java theme={null}
@Bean
public ChatClient chatClient(ChatModel chatModel) {
    return ChatClient.builder(chatModel)
        .defaultSystem("你是一个有用的AI助手，能够回答用户的问题并提供帮助。")
        .build();
}
```

### 创建自定义注解

现在，让我们创建`@AiPrompt`注解，它将用于标记需要AI处理的方法：

```java theme={null}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AiPrompt {
    String systemMessage() default "";
}
```

### 实现AOP切面

接下来，我们需要实现一个AOP切面来拦截带有`@AiPrompt`注解的方法调用：

```java theme={null}
@Aspect
@Component
@RequiredArgsConstructor
public class AiPromptAspect {

    private final 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`注解：

```java theme={null}
@Service
@RequiredArgsConstructor
public class ChatService {

    @AiPrompt(systemMessage = "你是一个专业的Java开发顾问，擅长解答Spring框架相关问题。")
    public String getJavaAdvice(String question) {
        return null; // 这个返回值会被AOP切面中的返回值覆盖
    }
}
```

### 控制器示例

最后，我们可以在控制器中使用这个服务：

```java theme={null}
@RestController
@RequestMapping("/api/chat")
@RequiredArgsConstructor
public class ChatController {

    private final ChatService chatService;
    
    @PostMapping("/java-advice")
    public String getJavaAdvice(@RequestBody String question) {
        return chatService.getJavaAdvice(question);
    }
}
```

## 总结

参考 LangChain4j 的高级 API 设计形式，基于 Spring AI 自定义注解实现的 AI services 可以有效地实现提示词模板的集中管理和复用，通过 AOP 机制自动处理 AI 接口的调用逻辑，显著提升开发效率。
这种模式不仅降低了与 AI 服务交互的代码复杂度，还通过标准化注解配置实现了以下优势：

* 1. 提示词工程的可维护性提升；

* 2. 业务代码与 AI 基础设施解耦；

* 3. 可以无缝集成 Spring 生态的其他能力，比如 Spring Cache 实现 AI注解式缓存
