AI| Spring AI Practice

简单使用

新建工程

首先我们需要新建一个项目,直接去Spring官方文档下面的Initializer设置

  • Spring 3.5.11
  • JDK17
  • Web Starter + Zhipu AI Starter

压缩包下下来之后解压IDE打开,获取智谱的api-key,放在配置文件

1
2
3
4
5
6
7
8
9
spring:
application:
name: ai-demo
ai:
zhipuai:
api-key: foo
chat:
options:
model: GLM-4-Flash

调用接口

在启动类包下新建一个Controller(还是Spring的规范)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@RestController
public class ChatController {

private final ZhiPuAiChatModel chatModel;

@Autowired
public ChatController(ZhiPuAiChatModel chatModel) {
this.chatModel = chatModel;
}

@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", chatModel.call(message));
}

@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
var prompt = new Prompt(new UserMessage(message));
return chatModel.stream(prompt);
}
}

之后进入接口测试即可获取模型返回

Prompt

角色

在了解 Prompt 之前我们需要先知道角色

在 Spring AI 中,将大模型和用户之间的交互流程抽象成了四种角色:

  • system: 系统角色,通常我们预设的提示词会和 system 角色关联
  • user: 用户角色,用于表示用户输入的文本,通常输入的提问会和 user 角色关联
  • assistant: 助手角色,用于表示模型生成的文本,通常大模型生成的答案会和 assistant 角色关联
  • tool: 工具角色,用于表示模型调用的函数返回的内容,会和 tool 角色关联

因此,如果希望调用时给模型定义身份,可以修改Prompt实例的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {

Prompt prompt = new Prompt(
//定义提示,包含系统预设和用户输入
Arrays.asList(new SystemMessage("你现在是一个专注于解决编码问题的助手"), new UserMessage(message)),
//定义模型调用的参数,如模型名称、温度、用户名称
ZhiPuAiChatOptions.builder()
.model(ZhiPuAiApi.ChatModel.GLM_4_Flash.getValue())
.temperature(0.7d)
.user("trevorlink")
.build()
);

Generation generation = chatModel.call(prompt).getResult();
return Map.of("generation", generation == null ? "" : generation.getOutput().getText());
}

PromptTemplate

在提示词有复用的场景,可以考虑Spring AI提供的提示词模板功能:根据固定的模板,在程序运行时结合Map动态替换修改。

这个简单了解即可,只需要知道:

  • 提示词模板实例可以生成系统提示词也可以生成用户提示词

  • 提示词具体的内容除了字符串硬编码,还可以通过配置文件定义后注入的方式兼容Spring生态

  • 一般通过提示词模板promptTemplate.create创建提示词,默认是创建UserMessage类型的消息;如果我们希望创建的是系统提示词可以使用SystemPromptTemplate

    1
    2
    3
    SystemPromptTemplate promptTemplate = new SystemPromptTemplate("我们现在开始角色扮演的聊天,你来扮演{personality}的{aiRole}, 我来扮演{myRole}");
    Message systemMsg = promptTemplate.createMessage(Map.of("personality", personality, "aiRole", aiRole, "myRole", myRole));
    Prompt prompt = new Prompt(systemMsg, new UserMessage(msg));

具体可以参考

结构转换

正常来说大模型返回的结构都是没有结构的,我们需要显式进行将返回的数据指定转换为业务对象模型

ChatClient

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RestController
public class StructureChatController {

private final ZhiPuAiChatModel chatModel;

public StructureChatController(ZhiPuAiChatModel chatModel) {
this.chatModel = chatModel;
}

@GetMapping("/ai/queryFilms")
public ActorsFilms queryFilms(@RequestParam(value = "actor") String actor) {
PromptTemplate template = new PromptTemplate("帮我返回五个{actor}导演的电影名,要求中文返回");
Prompt prompt = template.create(Map.of("actor", actor));
return ChatClient.create(chatModel)
.prompt(prompt)
.call()
.entity(ActorsFilms.class);
}

}

//record 关键字: 用于声明包含指定 final 属性的类的语法糖
record ActorsFilms(String actor, List<String> films) {}

BeanOutputConverter

也可以显式使用BeanOutputConverter基于ChatModel来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@RestController
public class StructureChatController {

private final ZhiPuAiChatModel chatModel;

public StructureChatController(ZhiPuAiChatModel chatModel) {
this.chatModel = chatModel;
}

@GetMapping("/ai/queryFilms2")
public ActorsFilms queryFilms2(@RequestParam(value = "actor") String actor) {
BeanOutputConverter<ActorsFilms> converter = new BeanOutputConverter<>(ActorsFilms.class);
String format = converter.getFormat();

PromptTemplate template = new PromptTemplate("""
帮我返回五个{actor}导演的电影名
{format}
""");
Prompt prompt = template.create(Map.of("actor", actor, "format", format));
Generation generation = chatModel.call(prompt).getResult();
if (generation == null) {
return null;
}
return converter.convert(generation.getOutput().getText());
}

}

record ActorsFilms(String actor, List<String> films) {}

这种方式虽然需要在 Prompt 模板中显式指定格式,但是准确性更可控

总结

使用 ChatClient 的方式本质上是通过Advisor从上下文获取信息注入到提示词,而 BenaOutputConverter 则是利用 Spring AI 的 Converter 具体实现.

上下文

和大模型的对话时,会将你们之前的对话内容也一并传给大模型,即:对于大模型而言,你的一次新的对话,它实际上把你们之前的所有对话都过了一遍;更专业一点的说法是你们的对话 是基于一个上下文,这个上下文会包含你之前和模型交互的所有内容。

若希望实现多轮对话,则每次和模型进行对话时,需要将之前和模型交互的所有内容都传递给模型,这样模型才能基于这些内容进行多轮的沟通。


AI| Spring AI Practice
http://example.com/2026/03/13/AI-Spring-AI-Practice/
作者
Noctis64
发布于
2026年3月13日
许可协议