Java + AI 应用入门

Spring AI ChatClient 入门:先在本地跑通调用链

用固定本地 ChatModel 理解 ChatClient、系统消息和用户消息;完整工程可在无模型密钥时运行。

Spring AI 的 ChatClient 把系统要求、用户问题和模型调用组织成一个调用链。先用本地固定的 ChatModel 跑通它,可以看清框架传递了什么,也能在没有模型密钥时复现结果。

本例固定 Spring AI 2.0.2、JDK 21、Maven 3.9.9,使用 Spring Boot 4.1.2 parent 管理依赖。官方兼容说明列出 Spring AI 2.0.x 支持 Boot 4.0.x/4.1.x;这里运行的是普通 Java 入口,没有启动 Boot Web 应用或验证自动配置。

配置工程

下载完整示例工程,解压进入 spring-ai 目录,使用 JDK 21 和 Maven 3.9.9 运行:

mvn package dependency:copy-dependencies -DincludeScope=runtime
java -cp 'target/classes:target/dependency/*' site.ChatClientDemo

首次构建需要下载公开依赖。命令使用 macOS/Linux 类路径分隔符;Windows 未在本轮验证。 本轮容器运行输出:

[本地固定响应] 线程池复用工作线程并管理并发资源。
modelCalls=1
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>4.1.2</version><relativePath/></parent>
  <groupId>site.cxykk.examples</groupId><artifactId>phase8-spring-ai</artifactId><version>1.0.0</version>
  <properties><java.version>21</java.version><spring-ai.version>2.0.2</spring-ai.version></properties>
  <dependencyManagement><dependencies>
    <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency>
  </dependencies></dependencyManagement>
  <dependencies>
    <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-client-chat</artifactId></dependency>
    <dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><scope>test</scope></dependency>
  </dependencies>
  <build><plugins>
    <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><version>3.8.1</version></plugin>
  </plugins></build>
</project>

工程只引入 ChatClient 模块,没有模型厂商 starter。这个选择意味着程序不会自动发现 API 密钥或向外部模型发请求。

用一个本地模型看清调用关系

LocalChatModel 实现 Spring AI 的 ChatModel 接口,接收 Prompt 后直接返回固定文字。它只是测试替身,不具有理解或生成能力。

package site;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.ai.chat.prompt.Prompt;

/** A deterministic test fixture. It never generates text using an LLM. */
public final class LocalChatModel implements ChatModel {
  private final Function<Prompt, String> response;
  public final AtomicInteger calls = new AtomicInteger();
  public Prompt lastPrompt;

  public LocalChatModel(Function<Prompt, String> response) { this.response = response; }

  @Override public ChatResponse call(Prompt prompt) {
    calls.incrementAndGet();
    lastPrompt = prompt;
    return new ChatResponse(List.of(new Generation(new AssistantMessage(response.apply(prompt)))));
  }
}
package site;

import org.springframework.ai.chat.client.ChatClient;

public final class ChatClientDemo {
  public static void main(String[] args) {
    var fixture = new LocalChatModel(prompt -> "[本地固定响应] 线程池复用工作线程并管理并发资源。");
    var client = ChatClient.builder(fixture).defaultSystem("用一句话回答 Java 问题。").build();
    String answer = client.prompt().user("什么是线程池?").call().content();
    if (answer == null || answer.isBlank()) throw new IllegalStateException("没有文本回答");
    System.out.println(answer);
    System.out.println("modelCalls=" + fixture.calls.get());
  }
}

defaultSystem 设置系统消息,user 提供用户问题,call().content() 走同步文本路径。自动测试检查两种消息仍然分别传到模型,并验证模型层异常会向调用者传播。固定响应不依赖问题内容,因此不能用这个例子评估回答质量。

接真实模型时仍需补哪些工作

真实接入需要选择相应 ChatModel 实现,核对厂商依赖、鉴权、模型名称、接口格式和超时。上一篇使用 Responses HTTP 格式,不表示所有 Spring AI 模型适配器都使用同一路径或支持相同功能。

如果通过 Spring Boot starter 创建客户端,还要单独验证自动配置、配置属性和真实模型连接。本文没有把这些未运行的步骤写成可直接复制的成功方案,也没有验证流式输出、重试、可观测性或生产部署。

接下来可以保留这个本地模型替身,把“问题前面增加资料”的过程独立测出来,再接真实模型。这就是下一篇最小 RAG 实验的范围。

继续学习

返回 Java + AI 应用入门目录