004_chat

31 阅读1分钟

通过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;
}