Spring AI 的初步实践与探索

引言

随着人工智能技术的快速发展,Spring AI 提供了一个强大的框架,让开发者能够轻松集成 AI 模型到 Spring Boot 应用中。本文将深入探讨如何通过 Spring AI 集成 DeepSeek 和 ZhiPu AI 模型,实现基础对话、流式输出、带记忆的会话以及 Function Call 的基础功能。无论你是初学者还是有经验的开发者,这篇博客都将为你提供清晰的实现路径和实用代码示例。

1. 项目初始化

Spring AI 是基于 Spring Boot 的 AI 集成框架,官方支持版本为 Spring Boot 3.2.x 和 3.3.x。更多详情可参考 Spring AI 官方文档

创建项目

使用 Spring Initializr 或你喜欢的 IDE 创建一个 Spring Boot 项目,确保选择兼容的版本。

2. 依赖配置

为了集成 AI 模型,我们需要引入相应的依赖。这里以 OpenAI 和 ZhiPu AI 模型为例,使用 BOM(Bill of Materials)统一管理版本。

OpenAI 模型依赖

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>

ZhiPu AI 模型依赖(用于 Function Call)

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>

BOM 版本管理

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

添加 Maven 仓库

由于部分依赖不在 Maven 中央仓库中,需要添加以下仓库:

<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots><enabled>false</enabled></snapshots>
    </repository>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/snapshot</url>
        <releases><enabled>false</enabled></releases>
    </repository>
    <repository>
        <id>central-portal-snapshots</id>
        <name>Central Portal Snapshots</name>
        <url>https://central.sonatype.com/repository/maven-snapshots/</url>
        <releases><enabled>false</enabled></releases>
        <snapshots><enabled>true</enabled></snapshots>
    </repository>
</repositories>

3. 配置文件设置

Spring AI 通过配置文件指定模型的请求地址、API Key 和参数。以下是两个模型的配置示例。

DeepSeek 模型配置

spring.ai.openai.base-url=https://api.deepseek.com
spring.ai.openai.api-key=${DS_AI_KEY}
spring.ai.openai.chat.options.model=deepseek-reasoner
spring.ai.openai.chat.options.temperature=0.7
  • temperature:控制生成内容的创造性,值越小越严谨,默认设为 0.7。

ZhiPu AI 模型配置

spring.ai.zhipuai.api-key=${ZP_AI_KEY}
spring.ai.zhipuai.chat.options.model=GLM-4-Plus
spring.ai.zhipuai.chat.options.temperature=0.7
  • ZhiPu AI 默认请求地址无需配置。

4. 实现基础 AI 接口

以下是使用 DeepSeek 模型实现基础对话和流式输出的代码。

@RestController
@RequestMapping("/ai")
public class ChatController {

    @Autowired
    private OpenAiChatModel chatModel;

    // 普通对话
    @GetMapping("/generate")
    public Map<String, String> generate(@RequestParam(defaultValue = "讲一个笑话") String message) {
        return Map.of("generation", chatModel.call(message));
    }

    // 流式输出(解决乱码问题)
    @GetMapping(value = "/generateStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatResponse> generateStream(@RequestParam(defaultValue = "讲一个笑话") String message) {
        Prompt prompt = new Prompt(new UserMessage(message));
        Flux<ChatResponse> stream = chatModel.stream(prompt);
        stream.subscribe(System.out::println);
        return stream;
    }
}

5. 实现带记忆的会话

为了支持上下文记忆和会话隔离,我们使用 InMemoryChatMemoryPromptChatMemoryAdvisor

@CrossOrigin
@RestController
@RequestMapping("/ai")
public class ChatController {

    @Autowired
    private OpenAiChatModel chatModel;

    private final InMemoryChatMemory memory = new InMemoryChatMemory();

    @GetMapping("/generateStreamWithMemory")
    public Flux<ChatResponse> generateStreamWithMemory(
            @RequestParam(defaultValue = "讲一个笑话") String prompt,
            @RequestParam("chatId") String chatId) {
        ChatClient client = ChatClient.builder(chatModel)
                .defaultAdvisors(new PromptChatMemoryAdvisor(memory))
                .build();
        return client.prompt()
                .user(prompt)
                .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
                .stream()
                .chatResponse();
    }
}
  • chatId:用于隔离不同会话。
  • CHAT_MEMORY_RETRIEVE_SIZE_KEY:设置记忆检索的最大消息数。

6. 实现 Function Call(基于 ZhiPu AI)

DeepSeek 不支持 Function Call,因此我们切换到 ZhiPu AI 模型。Function Call 允许模型调用外部工具获取实时信息或执行操作。

配置依赖和属性

已在第 2、3 节完成。

基础对话与流式输出

@RestController
@RequestMapping("/zp")
public class ZpChatController {

    @Autowired
    private ZhiPuAiChatModel chatModel;

    @GetMapping("/generate")
    public Map<String, String> generate(@RequestParam(defaultValue = "讲一个笑话") String prompt) {
        return Map.of("generation", chatModel.call(prompt));
    }

    @GetMapping(value = "/generateStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatResponse> generateStream(@RequestParam(defaultValue = "讲一个笑话") String message) {
        Prompt prompt = new Prompt(new UserMessage(message));
        return chatModel.stream(prompt);
    }
}

定义工具类

以下工具类用于获取当前时间和设置闹钟:

public class DateTimeTools {

    @Tool(description = "获取用户时区中的当前日期和时间")
    public String getCurrentDateTime() {
        return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
    }

    @Tool(description = "在指定时间后设置闹钟")
    public void setAlarm(
            @ToolParam(description = "当前时间,格式为 yyyy-MM-dd HH:mm:ss") String time,
            @ToolParam(description = "间隔时间(秒)") Long intervalSecond) {
        System.out.println("设置闹钟时间: " + time);
        System.out.println("间隔秒数: " + intervalSecond);
    }
}

测试 Function Call

@Test
void testFunctionCall() {
    String response = ChatClient.create(zhiPuAiChatModel)
            .prompt("在10分钟后设置一个闹钟")
            .tools(new DateTimeTools())
            .call()
            .content();
    System.out.println(response);
}

输出示例

设置闹钟时间: 2025-03-26 21:19:26
间隔秒数: 600
闹钟设置成功,将在10分钟后响起。

7. 总结与扩展

通过以上步骤,我们实现了从基础对话到带记忆会话,再到 Function Call 的完整功能。Spring AI 的灵活性使其成为 AI 集成的理想选择。想了解更多?请查阅以下资源:

希望这篇博客能为你的 Spring AI 之旅提供启发!有什么问题或建议,欢迎留言讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值