使用SpringAI框架对接Ollama本地模型、OpenAI模型
目录
概述
本文档介绍如何在 Spring AI 框架中同时对接 Ollama 本地模型和 OpenAI 模型,实现双渠道向量数据管理。
Spring AI官方文档:https://www.spring-doc.cn/projects/spring-ai#overview
双渠道对接的优势

- 两种方式的向量数据互不干扰
- 可以同时使用两种方案进行对比测试
- 方便迁移和切换
项目依赖配置
POM 文件配置
<dependencyManagement>
<dependencies>
<!-- 导入 Spring AI 的 BOM -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-M6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 使用 Spring AI 的依赖时,不需要写版本号 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
<!-- 版本由 BOM 统一管理,无需指定 -->
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pgvector-store</artifactId>
<!-- 版本由 BOM 统一管理,无需指定 -->
</dependency>
</dependencies>
YAML 配置文件
spring:
ai:
openai:
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
api-key:
embedding-model: text-embedding-v1
embedding:
options:
num-batch: 1536
ollama:
base-url:
mode:
embedding-model: nomic-embed-text
embedding:
options:
num-batch: 768
Ollama 配置
package cn.bugstack.knowledge.config;
import org.springframework.ai.ollama.OllamaEmbeddingModel;
import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.pgvector.PgVectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
@Configuration
public class OllamaConfig {
@Bean("ollamaSimpleVectorStore")
public SimpleVectorStore vectorStore(OllamaApi ollamaApi) {
OllamaEmbeddingModel embeddingModel = OllamaEmbeddingModel
.builder()
.ollamaApi(ollamaApi)
.defaultOptions(OllamaOptions.builder().model("nomic-embed-text").build())
.build();
return SimpleVectorStore.builder(embeddingModel).build();
}
@Bean("ollamaPgVectorStore")
public PgVectorStore pgVectorStore(OllamaApi ollamaApi, JdbcTemplate jdbcTemplate) {
OllamaEmbeddingModel embeddingModel = OllamaEmbeddingModel
.builder()
.ollamaApi(ollamaApi)
.defaultOptions(OllamaOptions.builder().model("nomic-embed-text").build())
.build();
return PgVectorStore.builder(jdbcTemplate, embeddingModel)
.vectorTableName("vector_store_ollama_deepseek")
.build();
}
}
OpenAI 配置
package cn.bugstack.knowledge.config;
import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.pgvector.PgVectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
@Configuration
public class OpenAIConfig {
@Value("${spring.ai.openai.base-url}")
private String baseUrl;
@Value("${spring.ai.openai.api-key}")
private String apiKey;
@Bean
public TokenTextSplitter tokenTextSplitter() {
return new TokenTextSplitter();
}
@Bean
public OpenAiApi openAiApi() {
return OpenAiApi.builder()
.baseUrl(baseUrl)
.apiKey(apiKey)
.build();
}
/**
* 创建基于内存的向量存储
* 特点:
* - 数据存储在应用内存中,重启后数据丢失
* - 适合开发测试、小规模数据场景
* - 无需外部数据库依赖,启动快速
*/
@Bean("openAiSimpleVectorStore")
public SimpleVectorStore vectorStore(OpenAiApi openAiApi) {
// 使用 OpenAI API 创建嵌入模型,用于将文本转换为向量
OpenAiEmbeddingModel embeddingModel = new OpenAiEmbeddingModel(openAiApi);
// 构建简单的向量存储,向量数据保存在内存中
return SimpleVectorStore.builder(embeddingModel).build();
}
/**
* 创建基于 PostgreSQL 的向量存储
* 特点:
* - 数据持久化存储在 PostgreSQL 数据库中
* - 支持 pgvector 扩展,提供高效的向量相似度搜索
* - 适合生产环境、大规模数据场景
* - 需要配置 PostgreSQL 数据库和 pgvector 扩展
*/
@Bean("openAiPgVectorStore")
public PgVectorStore pgVectorStore(OpenAiApi openAiApi, JdbcTemplate jdbcTemplate) {
// 使用 OpenAI API 创建嵌入模型
OpenAiEmbeddingModel embeddingModel = new OpenAiEmbeddingModel(openAiApi);
// 构建 PostgreSQL 向量存储
return PgVectorStore.builder(jdbcTemplate, embeddingModel)
.vectorTableName("vector_store_openai") // 指定数据库中存储向量的表名
.build();
}
}
向量数据库搭建
Docker 环境配置
数据库连接工具推荐使用 DBeaver 或 pgAdmin4。
# docker-compose-vector-db.yml
# 使用方法: docker-compose -f docker-compose-vector-db.yml up -d
version: '3'
services:
# PostgreSQL + pgvector 向量数据库
vector_db:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/pgvector:v0.5.0
container_name: vector_db
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=ai-rag-knowledge
- PGPASSWORD=postgres
volumes:
# 初始化 SQL 脚本(首次启动时执行)
- ./pgvector/sql/init.sql:/docker-entrypoint-initdb.d/init.sql
# 数据持久化(重要!避免容器重启后数据丢失)
- ./pgvector/data:/var/lib/postgresql/data
logging:
options:
max-size: 10m
max-file: "3"
ports:
- '15432:5432'
healthcheck:
test: "pg_isready -U postgres -d ai-rag-knowledge"
interval: 2s
timeout: 20s
retries: 10
networks:
- vector-network
networks:
vector-network:
driver: bridge
数据库初始化脚本
CREATE EXTENSION IF NOT EXISTS vector;
-- 查询表;SELECT * FROM information_schema.tables
-- 删除旧的表(如果存在)
DROP TABLE IF EXISTS public.vector_store_openai;
-- 创建新的表,使用UUID作为主键
CREATE TABLE public.vector_store_openai (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
content TEXT NOT NULL,
metadata JSONB,
embedding VECTOR(1536)
);
-- 删除旧的表(如果存在)
DROP TABLE IF EXISTS public.vector_store_ollama_deepseek;
-- 创建新的表,使用UUID作为主键
CREATE TABLE public.vector_store_ollama_deepseek (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
content TEXT NOT NULL,
metadata JSONB,
embedding VECTOR(768)
);
模型服务对接
Ollama 模型部署
由于 Ollama 本地安装后请求较慢(受机器配置限制),推荐采用线上 GPU 服务器小时付费方案。
推荐平台:京东云 GPU 服务器

使用方法:通过控制台拉取向量模型
ollama pull nomic-embed-text

OpenAI 模型对接
推荐使用阿里云百炼平台(兼容 OpenAI 接口):
平台地址:阿里云百炼

注意事项:需注意向量的维度配置。
功能测试验证
OpenAI 接口测试
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class OpenAiTest {
@Value("classpath:data/dog.png")
private Resource imageResource;
@Autowired
private OpenAiChatModel openAiChatModel;
@jakarta.annotation.Resource
private OpenAiApi openAiApi;
@Test
public void test_call() {
ChatResponse response = openAiChatModel.call(new Prompt(
"1+1",
OpenAiChatOptions.builder()
.model("qwen-turbo")
.build()));
log.info("测试结果(call):{}", JSON.toJSONString(response));
}
@Test
public void test_call_images() {
// 构建请求信息
UserMessage userMessage = new UserMessage("请描述这张图片的主要内容,并说明图中物品的可能用途。",
new Media(MimeType.valueOf(MimeTypeUtils.IMAGE_PNG_VALUE),
imageResource));
ChatResponse response = openAiChatModel.call(new Prompt(
userMessage,
OpenAiChatOptions.builder()
.model("qwen-vl-max")
.build()));
log.info("测试结果(images):{}", JSON.toJSONString(response));
}
}

Ollama 接口测试
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class OllamaTest {
@Resource
private OllamaChatModel ollamaChatModel;
@Value("classpath:data/dog.png")
private org.springframework.core.io.Resource imageResource;
@jakarta.annotation.Resource(name = "ollamaSimpleVectorStore")
private SimpleVectorStore simpleVectorStore;
@jakarta.annotation.Resource(name = "ollamaPgVectorStore")
private PgVectorStore pgVectorStore;
@jakarta.annotation.Resource
private TokenTextSplitter tokenTextSplitter;
@Test
public void test_model() {
ChatOptions defaultOptions = ollamaChatModel.getDefaultOptions();
}
@Test
public void test_call() {
ChatResponse response = ollamaChatModel.call(new Prompt(
"1+1",
OllamaOptions.builder().model("deepseek-r1:1.5b").build()));
log.info("测试结果(call):{}", JSON.toJSONString(response));
}
@Test
public void test_call_images() {
// 构建请求信息
UserMessage userMessage = new UserMessage("请描述这张图片的主要内容,并说明图中物品的可能用途。",
new Media(MimeType.valueOf(MimeTypeUtils.IMAGE_PNG_VALUE),
imageResource));
ChatResponse response = ollamaChatModel.call(new Prompt(
userMessage,
OllamaOptions.builder()
.model("deepseek-r1:1.5b")
.build()));
log.info("测试结果(images):{}", JSON.toJSONString(response));
}
}


浙公网安备 33010602011771号