通过spring ai 进行聊天简单案例
实现最基础的open ai,连接 xiaomi mimo 大模型,chat案例。chatClient实例需要先进行初始化。
pom 配置
<?xml version="1.0" encoding="UTF-8"?>
<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>
<groupId>com.youlangta</groupId>
<artifactId>003_spring_ai</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compliler.source>17</maven.compliler.source>
<maven.compliler.target>17</maven.compliler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<springboot.version>3.5.5</springboot.version>
<spring-ai-alibaba.version>1.0.0.2</spring-ai-alibaba.version>
<spring-ai-alibaba-extensions.version>1.0.0.2</spring-ai-alibaba-extensions.version>
<spring-ai.version>1.0.0</spring-ai.version>
<mysql-connector-java.version>8.0.33</mysql-connector-java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>${spring-ai-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
yml配置
spring:
ai:
openai:
api-key: xxx
base-url: https://dashscope.aliyuncs.com/compatible-mode
chat:
options:
# model: qwen-plus
model: mimo-v2-flash
api-key: xxx
base-url: https://api.xiaomimimo.com
代码
直接响应代码案例
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@RequestMapping("/doChat")
public String doChat(@RequestParam(name = "question") String question) {
return chatClient
.prompt()
.user(question)
.call()
.content();
}
流式响应代码案例
@RequestMapping(value = "/doChatStream", produces = "text/html;charset=UTF-8")
public Flux<String> doChatStream(@RequestParam(name = "question") String question) {
return chatClient
.prompt()
.user(question)
.stream()
.content();
}
sse响应代码案例
@RequestMapping(value = "/doChatSse")
public SseEmitter doChatSse(@RequestParam(name = "question") String question) {
SseEmitter sseEmitter = new SseEmitter() {
@Override
protected void extendResponse(ServerHttpResponse outputMessage) {
HttpHeaders headers = outputMessage.getHeaders();
headers.setContentType(new MediaType("text", "event-stream", StandardCharsets.UTF_8));
}
};
Flux<String> result = chatClient.prompt()
.user(question)
.stream()
.content();
result.subscribe(
token -> {
try {
sseEmitter.send(token);
} catch (IOException e) {
sseEmitter.completeWithError(e);
}
}
, sseEmitter::completeWithError, sseEmitter::complete);
return sseEmitter;
}
自定义返回结构体案例
@RequestMapping("/doChatOut")
public Poem doChatOut(@RequestParam(name = "question") String question) {
BeanOutputConverter<Poem> outputConverter = new BeanOutputConverter<>(new ParameterizedTypeReference<Poem>() {});
PromptTemplate promptTemplate = new PromptTemplate("写一篇关于{question}的七言绝句,{format}");
log.info("format:{}",outputConverter.getFormat());
String prompt = promptTemplate.render(Map.of("question", question, "format", outputConverter.getFormat()));
String content = chatClient
.prompt(prompt)
.call()
.content();
log.info("content:{}",content);
return outputConverter.convert(content);
}
@Data
private static class Poem {
private String title;
private String author;
private String content;
}