本文主要研究一下如何使用spring-ai-alibaba本地集成ollama+deepseek

步骤

pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.example</groupId>
   <artifactId>ollama-deepseek-chat</artifactId>
   <packaging>pom</packaging>
   <version>1.0.0-SNAPSHOT</version>

   <description>Spring AI Alibaba Ollama DeepSeek Chat Example</description>
   <name>Spring AI Alibaba Ollama DeepSeek Chat Examples</name>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>17</java.version>
      <maven.compiler.source>17</maven.compiler.source>
      <maven.compiler.target>17</maven.compiler.target>

      <!-- Spring AI -->
      <spring-ai.version>1.0.0-M5</spring-ai.version>

      <!-- Spring AI Alibaba -->
      <spring-ai-alibaba.version>1.0.0-M5.1</spring-ai-alibaba.version>

      <!-- Spring Boot -->
      <spring-boot.version>3.4.0</spring-boot.version>

      <!-- maven plugin -->
      <maven-deploy-plugin.version>3.1.1</maven-deploy-plugin.version>
      <flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
      <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
   </properties>

   <modules>
      <module>ollama-deepseek-chat-model</module>
      <module>ollama-deepseek-chat-client</module>
   </modules>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.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>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter</artifactId>
            <version>${spring-ai-alibaba.version}</version>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.ai</groupId>
         <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${spring-boot.version}</version>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>${maven-deploy-plugin.version}</version>
            <configuration>
               <skip>true</skip>
            </configuration>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven-compiler-plugin.version}</version>
            <configuration>
               <release>${java.version}</release>
               <compilerArgs>
                  <compilerArg>-parameters</compilerArg>
               </compilerArgs>
            </configuration>
         </plugin>
      </plugins>
   </build>

   <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>aliyunmaven</id>
         <name>aliyun</name>
         <url>https://maven.aliyun.com/repository/public</url>
      </repository>
   </repositories>

   <pluginRepositories>
      <pluginRepository>
         <id>public</id>
         <name>aliyun nexus</name>
         <url>https://maven.aliyun.com/repository/public</url>
         <releases>
            <enabled>true</enabled>
         </releases>
         <snapshots>
            <enabled>false</enabled>
         </snapshots>
      </pluginRepository>
   </pluginRepositories>

</project>
主要是引入spring-ai-ollama-spring-boot-starter

application.yaml

server:
  port: 10005

spring:
  application:
    name: spring-ai-alibaba-ollama-chat-model-example

  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        model: deepseek-r1:8b
这里配置ai.ollama.base-url、ai.ollama.chat.model

ChatModel

call

    @GetMapping("/simple/chat")
    public String simpleChat() {
        return ollamaChatModel.call(new Prompt(DEFAULT_PROMPT)).getResult().getOutput().getContent();
    }
使用call是阻塞一次性输出

stream

    @GetMapping("/stream/chat")
    public Flux<String> streamChat(HttpServletResponse response) {
        // 避免返回乱码
        response.setCharacterEncoding("UTF-8");

        Flux<ChatResponse> stream = ollamaChatModel.stream(new Prompt(DEFAULT_PROMPT));
        return stream.map(resp -> resp.getResult().getOutput().getContent());
    }
使用stream配合reactor的Flux就可以实现流式输出

也可以自定义options,之后传递给Prompt

OllamaOptions customOptions = OllamaOptions.builder()
                .withTopP(0.7)
                .withModel("llama3")
                .withTemperature(0.8)
                .build();
new Prompt(DEFAULT_PROMPT, customOptions)                

ChatClient

初始化

ChatClient ollamaiChatClient = ChatClient.builder(chatModel)
            // 实现 Chat Memory 的 Advisor
            // 在使用 Chat Memory 时,需要指定对话 ID,以便 Spring AI 处理上下文。
            .defaultAdvisors(
                  new MessageChatMemoryAdvisor(new InMemoryChatMemory())
            )
            // 实现 Logger 的 Advisor
            .defaultAdvisors(
                  new SimpleLoggerAdvisor()
            )
            // 设置 ChatClient 中 ChatModel 的 Options 参数
            .defaultOptions(
                  OllamaOptions.builder()
                        .withTopP(0.7)
                        .build()
            )
            .build();
ChatClient是在ChatModel的基础上做了进一步的封装,可以设置advisor

call

   @GetMapping("/simple/chat")
   public String simpleChat() {
      return ollamaiChatClient.prompt(DEFAULT_PROMPT).call().content();
   }
使用call是阻塞一次性输出

stream

   @GetMapping("/stream/chat")
   public Flux<String> streamChat(HttpServletResponse response) {
      response.setCharacterEncoding("UTF-8");
      return ollamaiChatClient.prompt(DEFAULT_PROMPT).stream().content();
   }
使用stream是流式输出

小结

spring-ai-alibaba提供了spring-ai-ollama-spring-boot-starter来集成ollama,通过ai.ollama.chat.model可以指定使用本地的deepseek-r1:8b。spring-ai-ollama-spring-boot-starter提供了基础的ChatModel以及高级版的ChatClient来调用ollama,ChatClient是在ChatModel的基础上做了进一步的封装,可以设置advisor,支持聊天记忆(Chat Memory)、工具/函数调用(Function Calling)、RAG。他们都提供了call及stream方式,call是阻塞一次性输出,stream是流式输出。

doc


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...