Spring AI集成Ollama:在Java应用中本地部署与调用大语言模型

📅 2026/6/16 15:22:01
Spring AI集成Ollama:在Java应用中本地部署与调用大语言模型
1. 项目概述Spring AI与Ollama的本地大模型集成最近在搞一个内部知识库问答系统不想把敏感数据送到云端就琢磨着在本地部署大模型。Ollama这个工具挺火的能一键拉取和运行各种开源模型而Spring AI作为Spring生态的AI集成框架提供了统一的操作接口。把这两者结合起来就能在熟悉的Spring Boot应用里轻松调用本地部署的LLM实现聊天、推理、多模态甚至工具调用这些高级功能。这不仅仅是技术选型更是一种架构思路将强大的AI能力以“基础设施”的方式低成本、高可控地集成到现有Java应用中。无论是快速验证一个AI点子还是构建严肃的生产级智能应用这个组合都提供了极大的灵活性。2. 核心思路与架构设计2.1 为什么是Spring AI Ollama选择这个组合背后有几个核心考量。首先是技术栈统一团队主力是Java/Spring技术栈引入Python或Node.js的AI服务会增加运维和集成的复杂度。Spring AI抽象了底层模型差异提供了一套统一的ChatModel、EmbeddingModel等API让开发者可以用同一种方式调用Ollama、OpenAI、Azure OpenAI等不同后端的模型极大降低了切换成本。其次是数据安全与成本可控。所有数据在本地流转完全规避了敏感数据上云的风险和合规问题。Ollama支持在消费级硬件甚至带GPU的笔记本上运行量化后的模型推理成本几乎为零特别适合对响应延迟要求不高、但数据隐私要求极高的内部工具或原型验证阶段。再者是开发体验与生态整合。Spring Boot的自动配置、外部化配置application.yml、依赖注入等特性让集成变得异常简单。你可以像配置一个数据库连接池一样配置你的AI模型服务。同时Spring AI天然支持与Spring生态的其他组件如Spring Data Vector Store用于RAGSpring Integration用于流程编排无缝集成为构建复杂的AI应用提供了坚实基础。2.2 整体架构与数据流一个典型的Spring AI Ollama应用架构可以分为三层。应用层是你的Spring Boot服务包含业务逻辑、控制器和Spring AI的ChatClient或ChatModelBean。AI抽象层由Spring AI提供它定义了标准的接口如ChatModel并提供了Ollama的具体实现OllamaChatModel。这一层负责将你的请求Prompt转换为Ollama API能理解的格式并将响应解析回来。模型服务层就是Ollama本身它作为一个独立的进程或容器运行管理着本地的模型文件并提供HTTP API供Spring AI调用。数据流也很清晰用户请求到达Spring MVC控制器 - 控制器调用注入的OllamaChatModel.call(Prompt)- Spring AI的Ollama客户端将请求封装为JSON通过HTTP发送到localhost:11434- Ollama服务加载模型并进行推理 - 推理结果通过HTTP返回 - Spring AI解析响应封装为ChatResponse对象 - 控制器将结果返回给用户。整个过程对开发者是透明的你只需要关心业务Prompt和结果处理。3. 环境准备与项目初始化3.1 Ollama的安装与模型部署第一步是在你的开发或服务器环境安装Ollama。访问Ollama官网下载对应操作系统的安装包是最直接的方式。对于国内用户从官网下载可能比较慢可以考虑使用国内镜像源加速。例如在Linux/macOS上可以通过修改环境变量来指定镜像源进行下载和拉取模型。安装完成后在终端运行ollama --version验证是否成功。Ollama安装好后核心操作是拉取模型。使用ollama pull model-name命令例如ollama pull llama3.2:3b。这里有几个实操要点一是模型选择对于入门和大多数应用场景llama3.2:3b、qwen2.5:3b这类较小的模型在8G内存的机器上就能流畅运行响应速度也较快。如果硬件资源充足如有NVIDIA GPU且显存8G可以尝试llama3.2:7b、qwen2.5:7b或deepseek-r1:7b等更大模型以获得更好效果。二是版本标签llama3.2:3b指定了模型家族和参数量你也可以拉取llama3.2:latest获取最新版本但在生产环境建议固定版本以避免不可预期的行为变化。注意首次拉取模型可能会耗时较长取决于模型大小和网络。建议在项目开发初期就提前下载好所需模型。可以通过ollama list查看已下载的模型。3.2 Spring Boot项目创建与依赖引入接下来创建Spring Boot项目。使用你最熟悉的工具比如Spring Initializrstart.spring.io选择最新的Spring Boot 3.x版本打包方式选Maven或Gradle语言选Java并添加Spring Web依赖。关键一步是添加Spring AI的Ollama starter依赖。由于Spring AI的版本管理独立于Spring Boot我们需要在pom.xml中先引入Spring AI的BOM物料清单来统一管理版本然后再添加具体依赖。Maven配置示例 (pom.xml):dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version1.0.0-M5/version !-- 使用最新稳定版 -- typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependencies !-- 其他依赖如 spring-boot-starter-web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI Ollama Starter -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-ollama-spring-boot-starter/artifactId /dependency /dependenciesGradle配置示例 (build.gradle):dependencyManagement { imports { mavenBom org.springframework.ai:spring-ai-bom:1.0.0-M5 } } dependencies { implementation org.springframework.boot:spring-boot-starter-web implementation org.springframework.ai:spring-ai-ollama-spring-boot-starter }引入BOM后所有Spring AI相关依赖的版本都会自动对齐避免版本冲突。添加完依赖一个基础的Spring AI Ollama项目骨架就准备好了。4. 核心配置详解与最佳实践4.1 基础连接与模型配置配置是发挥Spring Boot威力的地方。在application.yml或application.properties中我们可以细致地控制Ollama连接和模型行为。spring: ai: ollama: # Ollama服务地址默认本地11434端口 base-url: http://localhost:11434 # 初始化配置控制模型自动拉取行为 init: pull-model-strategy: when_missing # 可选: never, when_missing, always timeout: 10m # 拉取模型超时时间 max-retries: 1 # 拉取失败重试次数 # 聊天模型配置 chat: # 启用Ollama作为默认聊天模型 (Spring AI 1.x 配置方式) enabled: true # 指定使用的模型名称必须与ollama list中的名称一致 model: llama3.2:3b # 模型运行时参数 options: temperature: 0.7 # 创造性越高越随机 num-predict: 512 # 生成的最大token数-1表示无限制 top-k: 40 # 采样范围影响多样性 top-p: 0.9 # 核采样影响聚焦程度 repeat-penalty: 1.1 # 重复惩罚降低重复内容 num-ctx: 2048 # 上下文窗口大小这里有几个关键配置项需要理解。spring.ai.ollama.init.pull-model-strategy决定了应用启动时模型不存在怎么办。never默认要求模型必须已存在适合生产环境when_missing会在模型不存在时自动拉取适合开发always则每次启动都拉取确保是最新版但会严重拖慢启动速度。model参数必须与Ollama中拉取的模型名称完全一致。模型参数如temperature、top-p等直接影响生成质量。temperature温度控制随机性0.1-0.3适合事实性问答输出稳定0.7-0.9适合创意写作输出多样。num-predict限制生成长度防止模型“话痨”。num-ctx是上下文窗口决定了模型能“记住”多长的对话历史更大的窗口能处理更长的文档但也消耗更多内存。4.2 高级特性配置思考模式与结构化输出Ollama和Spring AI支持一些高级特性能显著提升应用能力。思考模式对于qwen3、deepseek-r1这类具备“思维链”能力的模型可以启用思考模式让模型先输出推理过程再给出最终答案。这在解决数学、逻辑问题时非常有用也便于调试。spring: ai: ollama: chat: options: model: deepseek-r1:7b # 启用思考模式仅支持该特性的模型 think: true在代码中你可以从响应元数据中提取思考内容ChatResponse response chatModel.call(prompt); String thinking response.getResult().getMetadata().get(thinking); String finalAnswer response.getResult().getOutput().getText();结构化输出这是生产级应用的关键。你可以要求模型严格按照指定的JSON Schema格式返回数据方便后端直接解析成对象。例如让模型总结一篇文章并返回标题、作者、关键点列表等结构化信息。spring: ai: ollama: chat: options: model: llama3.2:7b # 指定输出格式为JSON简单模式 format: json # 或者使用JSON Schema强制结构推荐 # 配置需通过代码中的OllamaChatOptions设置在代码中通过OllamaChatOptions的outputSchema方法设置JSON Schema字符串可以确保输出格式的确定性。4.3 多模型与运行时配置覆盖一个应用可能需要根据场景切换不同模型。Spring AI允许你定义多个ChatModelBean或者更灵活地在运行时通过Prompt的选项来覆盖默认配置。定义多个模型BeanConfiguration public class OllamaConfig { Bean Primary public OllamaChatModel defaultChatModel(OllamaApi ollamaApi) { return new OllamaChatModel(ollamaApi, OllamaChatOptions.builder() .model(llama3.2:3b) .temperature(0.7) .build()); } Bean public OllamaChatModel creativeChatModel(OllamaApi ollamaApi) { return new OllamaChatModel(ollamaApi, OllamaChatOptions.builder() .model(qwen2.5:7b) .temperature(0.9) // 更高的温度用于创意任务 .build()); } }运行时动态覆盖这是更常见的模式。在每次调用时通过Prompt传递特定的OllamaChatOptions来临时改变模型或参数。// 使用默认配置的模型进行一般对话 ChatResponse response1 chatModel.call(new Prompt(你好)); // 针对需要严谨回答的问题临时切换到更合适的模型并降低温度 OllamaChatOptions preciseOptions OllamaChatOptions.builder() .model(deepseek-r1:7b) // 切换模型 .temperature(0.2) // 降低随机性 .enableThinking() // 启用思考模式 .build(); Prompt precisePrompt new Prompt(计算15的平方根是多少, preciseOptions); ChatResponse response2 chatModel.call(precisePrompt);这种设计模式非常强大它允许你根据用户查询的意图、复杂度或领域动态选择最合适的模型和参数在效果和成本之间取得平衡。5. 核心API使用与代码实战5.1 基础聊天与流式响应Spring AI提供了同步和异步两种调用方式。同步调用call()会阻塞直到收到完整响应适合简单的问答。流式响应stream()则返回一个FluxChatResponse可以实时获取模型生成的每一个token适合需要逐步显示结果的场景如聊天界面。同步调用示例RestController RequestMapping(/api/chat) public class ChatController { private final ChatModel chatModel; // 由Spring自动注入OllamaChatModel PostMapping(/simple) public String simpleChat(RequestParam String message) { // 最简单的调用直接传入用户消息字符串 // Spring AI会将其包装为UserMessage并创建默认的Prompt String responseText chatModel.call(message); return responseText; } PostMapping(/advanced) public ChatResponse advancedChat(RequestBody ChatRequest request) { // 构建完整的Prompt包含系统指令和对话历史 SystemMessage systemMsg new SystemMessage(你是一个专业的Java开发助手。); UserMessage userMsg new UserMessage(request.getMessage()); // 如果有历史消息可以构建一个消息列表 ListMessage messages new ArrayList(); messages.add(systemMsg); messages.add(userMsg); Prompt prompt new Prompt(messages); ChatResponse response chatModel.call(prompt); // ChatResponse包含更丰富的信息输出内容、元数据、使用情况等 return response; } }流式响应示例GetMapping(value /stream, produces MediaType.TEXT_EVENT_STREAM_VALUE) public FluxString streamChat(RequestParam String query) { Prompt prompt new Prompt(new UserMessage(query)); return chatModel.stream(prompt) .map(ChatResponse::getResults) // 获取结果列表 .flatMap(List::stream) // 展开结果流 .map(Generation::getOutput) // 获取每个Generation的输出 .map(AssistantMessage::getContent) // 获取内容文本 .doOnNext(content - { // 可以在这里处理每个token如发送SSE事件 System.out.print(content); // 模拟实时输出 }); }流式响应需要客户端支持Server-Sent Events (SSE)或WebSocket。在浏览器中可以使用EventSourceAPI来接收这些数据块并实时更新UI。5.2 工具调用与函数执行工具调用是让大模型与现实世界交互的关键。Spring AI通过ToolCallingAdvisor和ChatClient提供了优雅的抽象。基本思路是你定义一些工具函数比如查询天气、搜索数据库、调用外部API将这些工具注册给模型模型在理解用户意图后会决定是否需要调用工具并以结构化格式请求调用你执行工具后把结果返回给模型模型再生成最终回答。定义工具函数首先创建一个工具类其中的方法就是模型可以调用的工具。Component public class WeatherService { ToolFunction(name getCurrentWeather, description 根据城市名称获取当前天气) public String getCurrentWeather( ToolParameter(description 城市名称例如北京、上海) String city) { // 这里模拟调用天气API MapString, String weatherData Map.of( 北京, 晴25°C, 上海, 多云23°C, 广州, 阵雨28°C ); return weatherData.getOrDefault(city, 未找到该城市天气信息); } ToolFunction(name searchKnowledgeBase, description 在内部知识库中搜索相关信息) public String searchKnowledgeBase( ToolParameter(description 搜索关键词) String keyword) { // 模拟搜索逻辑 return 找到关于\ keyword \的3条相关记录...; } }配置与使用工具调用在Spring配置中将工具服务注册为ToolCallback然后通过ChatClient使用。Configuration public class ToolConfig { Bean public ToolCallingAdvisor toolCallingAdvisor(WeatherService weatherService) { // 将工具服务转换为ToolCallback ToolCallback weatherCallback FunctionToolCallback.builder() .name(getCurrentWeather) .description(获取指定城市的当前天气) .inputType(String.class) // 工具参数类型 .function(weatherService::getCurrentWeather) .build(); return new ToolCallingAdvisor(List.of(weatherCallback)); } Bean public ChatClient chatClient(ChatModel chatModel, ToolCallingAdvisor advisor) { return ChatClient.builder(chatModel) .defaultAdvisors(advisor) // 注册工具调用顾问 .build(); } }在控制器中使用RestController public class ToolChatController { private final ChatClient chatClient; PostMapping(/chat-with-tools) public String chatWithTools(RequestParam String question) { // ChatClient会自动处理工具调用循环 String response chatClient.prompt() .user(question) .call() .content(); return response; } }当用户询问“北京和上海的天气怎么样”时模型会先识别出需要调用getCurrentWeather工具并分别请求北京和上海的天气。ChatClient会拦截这个工具调用请求执行实际的WeatherService.getCurrentWeather()方法将结果返回给模型模型再综合这些信息生成最终回答“北京晴25°C上海多云23°C。”整个过程对开发者基本透明大大简化了工具集成的复杂度。5.3 多模态处理与图像理解Ollama支持多模态模型如LLaVA可以处理图像输入。Spring AI通过Media类支持多模态消息。处理图像输入的示例PostMapping(value /analyze-image, consumes MediaType.MULTIPART_FORM_DATA_VALUE) public String analyzeImage(RequestParam(file) MultipartFile imageFile, RequestParam(question) String question) throws IOException { // 将上传的图像文件转换为Spring AI的Media对象 Media imageMedia new Media( MediaType.parseMediaType(imageFile.getContentType()), new ByteArrayResource(imageFile.getBytes()) ); // 构建包含图像和文本的多模态用户消息 UserMessage userMessage new UserMessage(question, List.of(imageMedia)); Prompt prompt new Prompt(userMessage); // 重要必须使用支持多模态的模型如llava OllamaChatOptions options OllamaChatOptions.builder() .model(llava:7b) // 指定多模态模型 .build(); prompt new Prompt(userMessage, options); ChatResponse response chatModel.call(prompt); return response.getResult().getOutput().getText(); }在这个例子中用户可以上传一张图片并提问“图片里有什么”或“描述一下这张图的内容”。模型会同时分析图像和文本生成结合视觉信息的回答。这对于构建图像描述、视觉问答、文档分析等应用非常有用。实操心得多模态模型通常比纯文本模型更大推理速度更慢且更耗资源。在实际应用中可以考虑异步处理图像分析请求或者提供进度提示。另外图像需要转换为base64编码或合适的资源格式传递给OllamaSpring AI的Media类帮我们处理了这些细节。6. 生产环境部署与优化策略6.1 性能调优与参数配置将Spring AI Ollama应用到生产环境性能是关键。以下是一些经过验证的优化策略。Ollama服务端优化GPU加速如果服务器有NVIDIA GPU确保Ollama使用了CUDA。安装时选择带GPU支持的版本运行时Ollama会自动检测并使用GPU。可以通过环境变量OLLAMA_NUM_GPU1强制指定或在模型配置中设置num_gpu参数。模型量化与选择生产环境优先考虑量化模型如llama3.2:7b-q4_K_M。这些模型在精度损失极小的情况下大幅减少了内存占用和计算需求。使用ollama pull llama3.2:7b-q4_K_M拉取量化版本。上下文长度与批处理根据实际需要调整num_ctx。不是越大越好2048对于大多数对话场景足够4096或8192适合长文档分析但会显著增加内存使用和推理时间。num_batch控制批处理大小增加它可以提高GPU利用率但也会增加显存压力需要根据硬件调整。保持模型常驻通过设置keep_alive参数如keep_alive: 30m让模型在请求后一段时间内保持在内存中避免频繁加载卸载的开销。对于高并发场景可以设置为较大的值或-1永久保持。Spring AI应用层优化连接池与超时Spring AI的Ollama客户端基于WebClient可以配置连接池和超时设置。在application.yml中spring: ai: ollama: base-url: http://localhost:11434 # 客户端配置 client: connect-timeout: 10s response-timeout: 60s # 长文本生成需要更长时间 read-timeout: 60s异步与非阻塞对于耗时较长的生成任务使用Spring WebFlux实现异步非阻塞响应避免阻塞Tomcat线程池。结合流式响应可以边生成边返回提升用户体验。缓存策略对于常见问题或模板化回答可以在应用层实现缓存。使用Spring Cache抽象将Prompt的哈希值作为key缓存ChatResponse。6.2 监控、日志与健康检查生产系统需要可观测性。Spring Boot Actuator提供了现成的监控端点可以轻松集成。添加Actuator依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependency配置健康检查Spring AI Ollama starter会自动注册一个健康指示器检查Ollama服务是否可达。management: endpoints: web: exposure: include: health,info,metrics endpoint: health: show-details: when_authorized访问/actuator/health可以看到Ollama连接状态。你还可以自定义健康检查比如测试模型是否正常响应。日志与追踪为了调试和审计需要记录详细的AI调用日志。可以配置一个ClientLogger拦截器Component public class OllamaRequestLogger implements ClientLogger { private static final Logger log LoggerFactory.getLogger(OllamaRequestLogger.class); Override public void log(String requestId, String request, String response) { // 注意生产环境不要记录完整的请求响应可能包含敏感数据 log.info(Ollama Request ID: {}, Model: {}, requestId, extractModel(request)); log.debug(Full request: {}, request); log.debug(Full response: {}, response); // 可以记录指标请求耗时、token使用量等 Metrics.counter(ai.requests.total).increment(); } private String extractModel(String requestJson) { try { JsonNode root new ObjectMapper().readTree(requestJson); return root.path(model).asText(unknown); } catch (Exception e) { return parse_error; } } }指标收集使用Micrometer集成Prometheus或OpenTelemetry收集关键指标请求速率QPS平均响应时间、P95/P99延迟Token消耗速率输入/输出错误率4xx/5xx响应模型加载/卸载次数这些指标能帮助你了解系统负载做出扩容或优化决策。6.3 安全与权限控制虽然Ollama在本地部署但安全仍然重要特别是当服务暴露给内部网络或多用户时。API认证与授权为你的Spring Boot应用添加安全层。使用Spring Security保护AI端点Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authz - authz .requestMatchers(/api/chat/**).authenticated() .requestMatchers(/api/admin/**).hasRole(ADMIN) .anyRequest().permitAll() ) .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) // 使用JWT .csrf(csrf - csrf.ignoringRequestMatchers(/api/chat/stream)); // 流式端点可能需要特殊处理 return http.build(); } }输入验证与防护对用户输入进行清理和验证防止Prompt注入攻击。Service public class PromptSanitizer { private static final SetString BLACKLISTED_PHRASES Set.of( ignore previous instructions, system prompt, 扮演, 模拟 // 根据业务需要添加更多 ); public String sanitize(String userInput) { if (userInput null || userInput.trim().isEmpty()) { throw new IllegalArgumentException(输入不能为空); } // 检查黑名单短语 String lowerInput userInput.toLowerCase(); for (String phrase : BLACKLISTED_PHRASES) { if (lowerInput.contains(phrase.toLowerCase())) { throw new SecurityException(输入包含不允许的指令); } } // 限制长度 if (userInput.length() 4000) { userInput userInput.substring(0, 4000) ...[已截断]; } // 移除控制字符可选 userInput userInput.replaceAll([\\p{Cntrl}[^\r\n\t]], ); return userInput; } }速率限制防止滥用为API添加速率限制。可以使用Spring的RateLimit注解或集成Resilience4jRestController public class RateLimitedChatController { private final RateLimiter rateLimiter; public RateLimitedChatController() { // 每个用户每分钟最多10次请求 this.rateLimiter RateLimiter.of(chat-api, RateLimiterConfig.custom() .limitForPeriod(10) .limitRefreshPeriod(Duration.ofMinutes(1)) .build()); } PostMapping(/api/chat) public ResponseEntityString chat(RequestParam String message, RequestHeader(X-User-ID) String userId) { // 基于用户ID的速率限制 if (!rateLimiter.acquirePermission(userId)) { return ResponseEntity.status(429) .header(Retry-After, 60) .body(请求过于频繁请稍后再试); } // 正常处理逻辑 String response chatModel.call(message); return ResponseEntity.ok(response); } }模型隔离在多租户场景可以为不同用户或组织分配不同的Ollama实例或使用不同的模型实现资源隔离。可以通过在请求头中指定模型动态创建OllamaChatModel实例。7. 常见问题排查与调试技巧7.1 连接与启动问题问题1应用启动时报错“Connection refused”或“Connect timed out”这通常表示Spring Boot应用无法连接到Ollama服务。首先检查Ollama是否正在运行在终端执行ollama serve或ollama run llama3.2看服务能否正常启动。然后验证端口Ollama默认使用11434端口确保没有被防火墙或其它进程占用。最后检查Spring配置确认application.yml中的spring.ai.ollama.base-url正确指向了Ollama服务地址。如果是Docker部署注意容器网络配置可能需要使用host网络或正确配置端口映射。问题2模型加载失败提示“model not found”这表示Ollama实例中没有你配置的模型。首先用ollama list确认模型是否存在。如果不存在使用ollama pull model-name拉取。注意模型名称大小写敏感必须完全匹配。如果是在集群或容器环境确保每个节点都有模型文件。对于生产环境建议将模型文件放在共享存储或使用初始化脚本预先拉取。问题3应用启动时卡在“Pulling model...”很久这是配置了spring.ai.ollama.init.pull-model-strategy: always或when_missing且模型需要下载。大型模型如7B、13B下载可能需要数十分钟取决于网络。对于生产环境建议设置为never并通过运维流程确保模型已预先存在。开发环境可以设置为when_missing但第一次启动要有耐心。可以查看Ollama服务的日志ollama serve的输出了解下载进度。7.2 运行时性能与稳定性问题问题4响应速度慢特别是首次请求首次请求慢是因为Ollama需要从磁盘加载模型到内存或GPU显存。可以通过设置keep_alive参数让模型常驻内存。在application.yml中配置spring.ai.ollama.chat.options.keep-alive: 30m这样模型在最后一次请求后30分钟内会保持在内存中。对于需要快速响应的生产服务可以设置为-1永久保持但要注意内存占用。问题5生成内容重复或质量差这通常与模型参数配置有关。调整以下参数可以改善降低temperature如从0.8降到0.3减少随机性增加repeat-penalty如从1.1升到1.5加强重复惩罚调整top-p和top-ktop-p: 0.9配合top-k: 40是平衡点想要更确定性的输出可以降低top-p到0.5确保num-predict设置合理太短可能截断回答太长可能产生无关内容问题6内存不足或OOM错误Ollama模型运行需要足够内存。3B模型约需要3-4GB7B模型需要7-8GB13B模型需要13GB以上。如果使用GPU部分层会加载到显存。解决方案使用量化版本模型如-q4_K_M后缀增加系统交换空间swap调整Ollama参数减少num_ctx上下文长度减少num_batch批处理大小升级硬件或使用更小模型7.3 高级功能与集成问题问题7工具调用不工作模型不识别工具首先确认Ollama版本至少是0.2.8工具调用功能的最低要求。使用ollama --version检查。然后检查工具函数定义确保ToolFunction注解正确参数有ToolParameter描述。在代码中确保ToolCallingAdvisor正确配置并注册到了ChatClient。可以通过开启DEBUG日志查看工具注册和调用过程logging.level.org.springframework.aiDEBUG。问题8结构化输出不符合预期结构化输出依赖模型的JSON生成能力。首先确保使用的是较新、能力强的模型如llama3.2、qwen2.5。其次JSON Schema要尽可能简单明确复杂的嵌套结构可能让模型困惑。可以先从简单结构开始测试。另外可以在Prompt中明确指示输出格式例如“请严格按照以下JSON格式回答{answer: 你的回答}”。如果问题依旧尝试调整temperature到更低值如0.1让输出更确定。问题9流式响应在客户端接收不完整这通常是客户端处理问题。确保客户端正确处理Server-Sent EventsSSE检查响应头Content-Type: text/event-stream检查连接保持SSE连接是长连接不能设置超时太短客户端实现使用标准的EventSourceAPI正确处理onmessage、onerror事件网络代理某些代理或负载均衡器可能不支持SSE需要特殊配置在服务端确保没有过滤器或拦截器修改了响应。Spring Security默认会缓存响应需要为流式端点禁用Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http .headers() .cacheControl().disable() // 禁用缓存 .and() // ... 其他配置 } }7.4 监控与日志调试技巧启用详细日志在application.yml中添加logging: level: org.springframework.ai: DEBUG org.springframework.web: DEBUG org.apache.http: DEBUG这会打印HTTP请求/响应详情包括发送给Ollama的完整Prompt和收到的原始响应对于调试复杂问题非常有用。使用Ollama API直接测试当问题难以定位时绕过Spring AI直接用curl测试Ollama APIcurl http://localhost:11434/api/generate -d { model: llama3.2:3b, prompt: 你好, stream: false }这能快速判断是Ollama问题还是Spring AI集成问题。性能分析工具使用JVM工具如VisualVM、JConsole监控应用内存和CPU使用。使用nvidia-smi如有GPU监控显存使用。对于Ollama本身可以查看其日志在Linux上Ollama日志通常在~/.ollama/logs/在Windows上在%USERPROFILE%\.ollama\logs\。编写集成测试为关键功能编写自动化集成测试确保升级或配置变更后核心功能正常SpringBootTest class OllamaIntegrationTest { Autowired private OllamaChatModel chatModel; Test void testBasicChat() { String response chatModel.call(你好请简单介绍一下你自己); assertNotNull(response); assertTrue(response.length() 10); } Test void testStreaming() { Prompt prompt new Prompt(写一首关于春天的短诗); FluxChatResponse stream chatModel.stream(prompt); ListString chunks stream .map(resp - resp.getResult().getOutput().getContent()) .collectList() .block(); assertNotNull(chunks); assertFalse(chunks.isEmpty()); } }定期运行这些测试可以在问题影响用户前及时发现。