本文主要展示下spring-ai ollama的使用

示例

pom.xml

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
        </dependency>
这里以ollama示例

配置

spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        model: qwen2.5:latest
这里使用qwen2.5

代码

    /**
     * Stream 流式调用。可以使大模型的输出信息实现打字机效果。
     * http://localhost:10005/ollama/chat-model/stream/chat?query=你好,介绍下你自己吧。请用中文回答。
     * @return Flux<String> types.
     */
    @GetMapping("/stream/chat")
    public Flux<String> streamChat(HttpServletResponse response,  @RequestParam("query") String query) {

        // 避免返回乱码
        response.setCharacterEncoding("UTF-8");

        Flux<ChatResponse> stream = ollamaChatModel.stream(new Prompt(query));
        return stream.map(resp -> resp.getResult().getOutput().getContent());
    }

返回

您好!我叫Qwen,是由阿里云开发的大型语言模型。我的主要功能是生成各种文本内容,例如文章、故事、诗歌等,并能根据您的需求提供信息查询、对话互动等服务。我会不断学习和进步,尽力为用户提供准确且有用的信息。有什么问题或需要帮助的吗?

源码

spring-ai-ollama-spring-boot-starter

spring-ai-ollama-spring-boot-starter-1.0.0-M5.jar!/META-INF/maven/org.springframework.ai/spring-ai-ollama-spring-boot-starter/pom.xml

<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>3.3.6</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-spring-boot-autoconfigure</artifactId>
      <version>1.0.0-M5</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-ollama</artifactId>
      <version>1.0.0-M5</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
spring-ai-ollama-spring-boot-starter的pom文件引入了spring-ai-spring-boot-autoconfigure及spring-ai-ollama

spring-ai-spring-boot-autoconfigure

spring-ai-spring-boot-autoconfigure-1.0.0-M5.jar!/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration
org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration
org.springframework.ai.autoconfigure.oci.genai.OCIGenAiAutoConfiguration
org.springframework.ai.autoconfigure.stabilityai.StabilityAiImageAutoConfiguration
org.springframework.ai.autoconfigure.transformers.TransformersEmbeddingModelAutoConfiguration
org.springframework.ai.autoconfigure.huggingface.HuggingfaceChatAutoConfiguration
org.springframework.ai.autoconfigure.vertexai.gemini.VertexAiGeminiAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.jurrasic2.BedrockAi21Jurassic2ChatAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.llama.BedrockLlamaChatAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.cohere.BedrockCohereChatAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.cohere.BedrockCohereEmbeddingAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.anthropic.BedrockAnthropicChatAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.anthropic3.BedrockAnthropic3ChatAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.titan.BedrockTitanChatAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.titan.BedrockTitanEmbeddingAutoConfiguration
org.springframework.ai.autoconfigure.bedrock.converse.BedrockConverseProxyChatAutoConfiguration
org.springframework.ai.autoconfigure.chat.observation.ChatObservationAutoConfiguration
org.springframework.ai.autoconfigure.embedding.observation.EmbeddingObservationAutoConfiguration
org.springframework.ai.autoconfigure.image.observation.ImageObservationAutoConfiguration
org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration
org.springframework.ai.autoconfigure.mistralai.MistralAiAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.oracle.OracleVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.pgvector.PgVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.pinecone.PineconeVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.chroma.ChromaVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.azure.AzureVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.weaviate.WeaviateVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.neo4j.Neo4jVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.hanadb.HanaCloudVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.cosmosdb.CosmosDBVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.mariadb.MariaDbStoreAutoConfiguration
org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration
org.springframework.ai.autoconfigure.postgresml.PostgresMlAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.mongo.MongoDBAtlasVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.anthropic.AnthropicAutoConfiguration
org.springframework.ai.autoconfigure.watsonxai.WatsonxAiAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.elasticsearch.ElasticsearchVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.gemfire.GemFireVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.cassandra.CassandraVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration
org.springframework.ai.autoconfigure.chat.client.ChatClientAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.typesense.TypesenseVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.opensearch.OpenSearchVectorStoreAutoConfiguration
org.springframework.ai.autoconfigure.moonshot.MoonshotAutoConfiguration
org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration
org.springframework.ai.autoconfigure.minimax.MiniMaxAutoConfiguration
org.springframework.ai.autoconfigure.vertexai.embedding.VertexAiEmbeddingAutoConfiguration
org.springframework.ai.autoconfigure.chat.memory.cassandra.CassandraChatMemoryAutoConfiguration
org.springframework.ai.autoconfigure.vectorstore.observation.VectorStoreObservationAutoConfiguration
spring-ai-spring-boot-autoconfigure定义了如上这些imports,这里包含了org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration

OllamaAutoConfiguration

org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java

@AutoConfiguration(after = RestClientAutoConfiguration.class)
@ConditionalOnClass(OllamaApi.class)
@EnableConfigurationProperties({ OllamaChatProperties.class, OllamaEmbeddingProperties.class,
        OllamaConnectionProperties.class, OllamaInitializationProperties.class })
@ImportAutoConfiguration(classes = { RestClientAutoConfiguration.class, WebClientAutoConfiguration.class })
public class OllamaAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(OllamaConnectionDetails.class)
    public PropertiesOllamaConnectionDetails ollamaConnectionDetails(OllamaConnectionProperties properties) {
        return new PropertiesOllamaConnectionDetails(properties);
    }

    @Bean
    @ConditionalOnMissingBean
    public OllamaApi ollamaApi(OllamaConnectionDetails connectionDetails,
            ObjectProvider<RestClient.Builder> restClientBuilderProvider,
            ObjectProvider<WebClient.Builder> webClientBuilderProvider) {
        return new OllamaApi(connectionDetails.getBaseUrl(),
                restClientBuilderProvider.getIfAvailable(RestClient::builder),
                webClientBuilderProvider.getIfAvailable(WebClient::builder));
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = OllamaChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
            matchIfMissing = true)
    public OllamaChatModel ollamaChatModel(OllamaApi ollamaApi, OllamaChatProperties properties,
            OllamaInitializationProperties initProperties, List<FunctionCallback> toolFunctionCallbacks,
            FunctionCallbackResolver functionCallbackResolver, ObjectProvider<ObservationRegistry> observationRegistry,
            ObjectProvider<ChatModelObservationConvention> observationConvention) {
        var chatModelPullStrategy = initProperties.getChat().isInclude() ? initProperties.getPullModelStrategy()
                : PullModelStrategy.NEVER;

        var chatModel = OllamaChatModel.builder()
            .ollamaApi(ollamaApi)
            .defaultOptions(properties.getOptions())
            .functionCallbackResolver(functionCallbackResolver)
            .toolFunctionCallbacks(toolFunctionCallbacks)
            .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
            .modelManagementOptions(
                    new ModelManagementOptions(chatModelPullStrategy, initProperties.getChat().getAdditionalModels(),
                            initProperties.getTimeout(), initProperties.getMaxRetries()))
            .build();

        observationConvention.ifAvailable(chatModel::setObservationConvention);

        return chatModel;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = OllamaEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
            matchIfMissing = true)
    public OllamaEmbeddingModel ollamaEmbeddingModel(OllamaApi ollamaApi, OllamaEmbeddingProperties properties,
            OllamaInitializationProperties initProperties, ObjectProvider<ObservationRegistry> observationRegistry,
            ObjectProvider<EmbeddingModelObservationConvention> observationConvention) {
        var embeddingModelPullStrategy = initProperties.getEmbedding().isInclude()
                ? initProperties.getPullModelStrategy() : PullModelStrategy.NEVER;

        var embeddingModel = OllamaEmbeddingModel.builder()
            .ollamaApi(ollamaApi)
            .defaultOptions(properties.getOptions())
            .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
            .modelManagementOptions(new ModelManagementOptions(embeddingModelPullStrategy,
                    initProperties.getEmbedding().getAdditionalModels(), initProperties.getTimeout(),
                    initProperties.getMaxRetries()))
            .build();

        observationConvention.ifAvailable(embeddingModel::setObservationConvention);

        return embeddingModel;
    }

    @Bean
    @ConditionalOnMissingBean
    public FunctionCallbackResolver springAiFunctionManager(ApplicationContext context) {
        DefaultFunctionCallbackResolver manager = new DefaultFunctionCallbackResolver();
        manager.setApplicationContext(context);
        return manager;
    }

    static class PropertiesOllamaConnectionDetails implements OllamaConnectionDetails {

        private final OllamaConnectionProperties properties;

        PropertiesOllamaConnectionDetails(OllamaConnectionProperties properties) {
            this.properties = properties;
        }

        @Override
        public String getBaseUrl() {
            return this.properties.getBaseUrl();
        }

    }

}
OllamaAutoConfiguration配置了PropertiesOllamaConnectionDetails、OllamaApi、OllamaChatModel、OllamaEmbeddingModel、FunctionCallbackResolver

小结

spring ai提供了spring-ai-ollama-spring-boot-starter用于集成ollma,OllamaAutoConfiguration自动配置了OllamaApi、OllamaChatModel。

doc


codecraft
11.9k 声望2k 粉丝

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