ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Spring AI实战:从零构建大模型智能体应用与AI小镇模拟

Spring AI实战:从零构建大模型智能体应用与AI小镇模拟 1. 引言从“AI末日论”到工程实践最近关于“AI末日论”的讨论在科技圈甚嚣尘上一些声音将人工智能描绘成人类生存的潜在威胁。然而正如万斯所言这种论调在某种程度上更像是为了吸引眼球、获取资源的“病毒式营销”。对于广大开发者而言与其陷入对遥远未来的恐慌性争论不如脚踏实地聚焦于当下AI技术的工程化实践与应用开发。AI并非遥不可及的科幻概念它已经以“智能体Agent”、“大模型应用开发”、“AI编程助手”等形式深度融入我们的日常开发工作流。本文将彻底抛开空泛的讨论直击核心为开发者呈现一套从理论到实践的AI应用开发全景指南。我们将从当前最热门的“AI智能体”和“Spring AI”框架入手手把手带你搭建开发环境、集成大模型、构建具备复杂推理能力的应用并最终部署一个可交互的AI小镇模拟项目。无论你是想探索AI应用开发的新手还是希望将大模型能力集成到现有Java/Spring生态中的资深工程师这篇文章都将提供清晰、完整、可复现的路径。2. AI工程化核心概念与技术栈梳理在进入实战之前我们有必要厘清几个关键概念它们构成了当前AI应用开发的基石。2.1 大模型与AI智能体大模型如GPT-4、Claude、通义千问等是一种基于海量数据训练、拥有数百亿甚至数千亿参数的深度学习模型。它们具备强大的语言理解、生成和推理能力是AI应用的“大脑”。开发者通常通过API调用的方式使用它们。AI智能体这是当前工程化的热点。一个智能体不仅仅是一个聊天接口它是一个能够感知环境、进行决策、执行动作以完成特定目标的系统。它通常由以下几部分组成规划分解任务制定步骤。记忆保存对话历史、工具调用结果等上下文。工具使用调用外部API、数据库、搜索引擎等扩展能力。行动执行规划好的步骤。2.2 相关技术框架与工具Spring AI一个由Spring官方社区孵化的项目旨在将大模型能力无缝集成到Spring生态系统中。它提供了统一的API抽象了不同大模型供应商如OpenAI、Azure OpenAI、Ollama的差异让开发者能以熟悉的Spring风格如RestTemplate、Spring Boot Auto-configuration来调用AI功能。它是Java后端开发者进入AI世界最友好的桥梁。AI编程助手如Cursor、GitHub Copilot、通义灵码等。这些工具基于大模型能实现代码补全、解释、重构、生成测试用例等极大提升开发效率。它们代表了大模型在软件开发垂直领域的落地应用。本地模型部署为了满足数据隐私、定制化或成本控制的需求许多开发者开始关注如何在本地或私有云上运行开源大模型如Llama 3、Qwen、ChatGLM。工具如Ollama、vLLM、LM Studio使得本地运行和调试大模型变得简单。AI应用开发模式从简单的Prompt工程到RAG检索增强生成再到多智能体协作系统开发模式正在快速演进。3. 环境准备与项目初始化我们将以一个“智能天气查询与旅行建议助手”项目作为主线演示如何使用Spring AI构建一个完整的AI应用。最终我们会扩展到介绍一个更复杂的多智能体协作项目“AI小镇”。3.1 基础环境要求操作系统macOS / Windows (WSL2推荐) / LinuxJava开发套件JDK 17 或更高版本Spring AI 需要 JDK 17构建工具Apache Maven 3.6 或 Gradle 7.x集成开发环境IntelliJ IDEA推荐对Spring Boot支持最佳或 VS Code版本控制Git3.2 创建Spring Boot项目最快的方式是使用 Spring Initializr 。Project: MavenLanguage: JavaSpring Boot: 3.2.x (确保版本与Spring AI兼容)Dependencies: 添加Spring Web和Spring AI。注意Spring Initializr可能尚未直接收录Spring AI我们需要手动添加依赖。3.3 手动配置Maven依赖创建项目后打开pom.xml文件添加Spring AI的BOM物料清单和具体模块依赖。Spring AI版本请查询官方文档获取最新稳定版。?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.5/version !-- 使用与Spring AI兼容的版本 -- relativePath/ /parent groupIdcom.example/groupId artifactIdai-weather-assistant/artifactId version0.0.1-SNAPSHOT/version nameai-weather-assistant/name descriptionAI Weather Assistant powered by Spring AI/description properties java.version17/java.version spring-ai.version0.8.1/spring-ai.version !-- 示例版本请检查更新 -- /properties dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI OpenAI 集成 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId /dependency !-- 用于测试 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin /plugins /build /project3.4 配置大模型连接我们需要一个真实的大模型来驱动应用。这里以OpenAI的GPT模型为例。在src/main/resources/application.properties中配置# OpenAI API 配置 spring.ai.openai.api-key${OPENAI_API_KEY:your-api-key-here} spring.ai.openai.chat.options.modelgpt-3.5-turbo # 可选配置代理如需 # spring.ai.openai.base-urlhttps://api.openai.com/v1重要your-api-key-here需要替换为你自己的OpenAI API Key。切勿将真实的API Key提交到公开的代码仓库。最佳实践是使用环境变量export OPENAI_API_KEYsk-你的真实key然后在配置文件中使用spring.ai.openai.api-key${OPENAI_API_KEY}。4. 核心开发构建天气查询AI助手现在我们开始编写核心业务逻辑。这个助手将能理解用户关于天气和旅行的自然语言提问并给出建议。4.1 创建核心服务AiWeatherService首先我们创建一个服务类它利用Spring AI的ChatClient与模型交互。// 文件路径src/main/java/com/example/aiweatherassistant/service/AiWeatherService.java package com.example.aiweatherassistant.service; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.PromptTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.Map; Service public class AiWeatherService { private final ChatClient chatClient; private final RestTemplate restTemplate; // 假设我们有一个免费的天气API这里用Open-Meteo示例 Value(${weather.api.url:https://api.open-meteo.com/v1/forecast}) private String weatherApiUrl; Autowired public AiWeatherService(ChatClient.Builder chatClientBuilder, RestTemplate restTemplate) { this.chatClient chatClientBuilder.build(); this.restTemplate restTemplate; } /** * 获取真实天气数据模拟 */ public String fetchRealWeather(String city) { // 这里简化处理实际应调用天气API并解析JSON // 例如https://api.open-meteo.com/v1/forecast?latitude52.52longitude13.41current_weathertrue String mockWeather String.format(当前%s的天气模拟数据晴温度25°C湿度60%%风速3级。, city); return mockWeather; } /** * 核心方法处理用户查询整合天气数据并让AI生成建议 */ public String getTravelAdvice(String userQuestion) { // 1. 从用户问题中提取城市这里使用简单的Prompt工程生产环境可用NLP模型 String extractedCity extractCityFromQuestion(userQuestion); if (extractedCity null) { extractedCity 北京; // 默认城市 } // 2. 获取该城市的天气信息 String weatherInfo fetchRealWeather(extractedCity); // 3. 构建给AI的Prompt提供上下文和指令 String promptTemplate 你是一个专业的旅行和天气助手。 请根据以下真实天气数据和用户的问题提供友好、详细且实用的建议。 真实天气数据 {weather} 用户的问题 {question} 请用中文回答并确保建议基于提供的天气数据。如果天气数据中不包含用户关心的方面如降水概率请基于常识进行合理推断并说明。 ; PromptTemplate pt new PromptTemplate(promptTemplate); Prompt prompt pt.create(Map.of( weather, weatherInfo, question, userQuestion )); // 4. 调用AI模型生成回复 ChatResponse response chatClient.prompt(prompt) .call() .chatResponse(); return response.getResult().getOutput().getContent(); } /** * 简易城市提取示例实际应用需要更复杂的NLP处理 */ private String extractCityFromQuestion(String question) { // 这里只是一个非常简单的关键字匹配生产环境应使用更可靠的方法 String[] cities {北京, 上海, 广州, 深圳, 杭州, 成都, 纽约, 伦敦, 东京}; for (String city : cities) { if (question.contains(city)) { return city; } } return null; } }4.2 创建RESTful API控制器接下来创建一个简单的控制器来暴露服务接口。// 文件路径src/main/java/com/example/aiweatherassistant/controller/WeatherAssistantController.java package com.example.aiweatherassistant.controller; import com.example.aiweatherassistant.service.AiWeatherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/api/ai-assistant) public class WeatherAssistantController { private final AiWeatherService aiWeatherService; Autowired public WeatherAssistantController(AiWeatherService aiWeatherService) { this.aiWeatherService aiWeatherService; } PostMapping(/ask) public String askAssistant(RequestBody AskRequest request) { if (request null || request.getQuestion() null || request.getQuestion().trim().isEmpty()) { return 请提出一个关于天气或旅行的问题。; } return aiWeatherService.getTravelAdvice(request.getQuestion()); } // 简单的请求体 public static class AskRequest { private String question; // getter and setter public String getQuestion() { return question; } public void setQuestion(String question) { this.question question; } } }4.3 创建应用主类// 文件路径src/main/java/com/example/aiweatherassistant/AiWeatherAssistantApplication.java package com.example.aiweatherassistant; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; SpringBootApplication public class AiWeatherAssistantApplication { public static void main(String[] args) { SpringApplication.run(AiWeatherAssistantApplication.class, args); } Bean public RestTemplate restTemplate() { return new RestTemplate(); } }5. 运行、测试与验证5.1 启动应用在项目根目录下运行mvn spring-boot:run或直接在IDE中运行AiWeatherAssistantApplication主类。看到类似以下的日志说明启动成功Started AiWeatherAssistantApplication in 5.123 seconds5.2 测试API使用curl或 Postman 等工具测试我们的AI助手。curl -X POST http://localhost:8080/api/ai-assistant/ask \ -H Content-Type: application/json \ -d {question: 我明天要去上海出差天气怎么样需要带伞吗}预期响应示例“根据模拟数据当前上海的天气为晴温度25°C湿度60%风速3级。明天上海是晴天温度适宜湿度适中风速不大。因此您不需要带伞。建议穿着轻便的衣物做好防晒即可。祝您出差顺利”5.3 单元测试为服务层编写一个简单的单元测试使用Spring AI的测试支持或Mock。// 文件路径src/test/java/com/example/aiweatherassistant/service/AiWeatherServiceTest.java package com.example.aiweatherassistant.service; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import static org.assertj.core.api.Assertions.assertThat; SpringBootTest class AiWeatherServiceTest { Autowired private AiWeatherService aiWeatherService; Test void testGetTravelAdvice_ContainsCityAndAdvice() { // 注意这是一个集成测试会真实调用配置的AI API消耗Token // 在生产测试中应使用MockBean来模拟ChatClient String question 北京周末天气如何适合户外活动吗; String answer aiWeatherService.getTravelAdvice(question); assertThat(answer).isNotBlank(); assertThat(answer.toLowerCase()).contains(北京); // 可以根据AI回答的常见关键词进行断言 assertThat(answer).containsAnyOf(天气, 建议, 温度, 适合); System.out.println(AI回复: answer); } }6. 进阶集成本地模型与智能体框架使用OpenAI等云端API虽然方便但存在成本、延迟和数据隐私考量。下面我们看如何集成本地模型。6.1 使用Ollama运行本地模型安装Ollama访问 Ollama官网 下载并安装。拉取并运行模型ollama pull llama3:8b # 拉取Llama 3 8B模型 ollama run llama3:8b # 运行模型会在本地启动一个API服务Ollama默认在http://localhost:11434提供兼容OpenAI的API。6.2 配置Spring AI连接Ollama修改application.properties# 切换到 Ollama 本地模型 spring.ai.openai.base-urlhttp://localhost:11434 spring.ai.openai.chat.options.modelllama3:8b # Ollama 通常不需要api-key但可以配置一个 dummy key spring.ai.openai.api-keydummy-key重启应用现在你的AI助手将使用本地运行的Llama 3模型进行推理。6.3 引入更复杂的智能体逻辑上面的例子是一个简单的“一问一答”模式。真正的智能体需要记忆、规划和工具使用。我们可以利用ChatClient的流式响应和函数调用能力进行扩展。// 示例让AI决定是否需要调用外部工具 public String advancedAssistant(String query) { // 定义工具函数供AI调用 var toolSpec FunctionCallback.builder() .name(getWeather) .description(根据城市名称获取实时天气) .inputType(WeatherRequest.class) // 自定义输入类 .function(city - fetchRealWeather(city.name())) .build(); var chatClient ChatClient.builder(chatModel) .defaultFunctions(getWeather) // 注册工具 .build(); // 构建包含系统指令的Prompt var systemMessage 你是一个高级助手。当用户询问天气时你必须调用getWeather工具获取数据后再回答。 对于其他问题直接回答。 ; var userMessage new UserMessage(query); var prompt new Prompt(List.of(new SystemMessage(systemMessage), userMessage)); var response chatClient.prompt(prompt).call().chatResponse(); // 处理可能包含工具调用结果的响应 return response.getResult().getOutput().getContent(); }7. 扩展实践探索“AI小镇”多智能体项目“AI小镇”是一个著名的开源多智能体模拟项目它生动展示了多个AI智能体如何在一个虚拟环境中生活、社交和协作。这代表了AI工程化更前沿的方向。7.1 项目概览项目地址https://github.com/mewamew/my_ai_town(请注意这是一个示例链接实际热门项目可能是https://github.com/joonspk-research/generative_agents或类似)核心思想每个居民是一个独立的AI智能体拥有记忆、日程、人际关系。他们能基于过去的互动和当前环境做出决策。技术栈通常涉及大模型API、向量数据库存储记忆、智能体框架如LangChain, AutoGen、前端可视化。7.2 从我们的项目到“AI小镇”的演进思路从单一到多智能体我们的天气助手是一个单一智能体。AI小镇需要管理数十上百个智能体每个都运行着类似的AI推理循环。记忆系统为每个智能体引入向量数据库如Chroma, Pinecone来存储和检索长期记忆。环境模拟创建一个虚拟的世界状态所有智能体共享并可以感知和改变它。通信机制定义智能体之间如何交流例如通过自然语言消息广播或定向发送。调度与并发需要一个中央调度器来推进模拟时间并管理所有智能体的并发推理请求。7.3 简易多智能体模拟代码结构示例// 简化的智能体类 public class GenerativeAgent { private String name; private String description; // 角色描述 private VectorStore memoryStore; // 记忆存储 private ChatClient aiEngine; // 推理引擎 public String perceive(String observation) { // 1. 将观察存入记忆 memoryStore.add(observation); // 2. 从记忆中检索相关上下文 ListString relevantMemories memoryStore.search(observation); // 3. 构建Prompt包含角色描述、相关记忆、当前观察 String prompt buildPrompt(observation, relevantMemories); // 4. 调用AI决定行动 return aiEngine.prompt(prompt).call().chatResponse().getResult().getOutput().getContent(); } } // 模拟环境 Service public class AiTownSimulation { private ListGenerativeAgent agents; private ScheduledExecutorService scheduler; PostConstruct public void init() { agents createAgents(); // 初始化一群智能体 scheduler.scheduleAtFixedRate(this::runSimulationStep, 0, 1, TimeUnit.MINUTES); } private void runSimulationStep() { // 更新世界状态如时间从早上变为中午 // 让每个智能体感知环境并行动 for (GenerativeAgent agent : agents) { String observation generateObservationFor(agent); String action agent.perceive(observation); executeAction(agent, action); // 执行行动可能影响环境或其他智能体 } } }8. 常见问题、排查与优化8.1 常见问题与解决方案问题现象可能原因排查与解决思路应用启动失败报错No qualifying bean of type ChatClientSpring AI 依赖未正确引入或版本冲突。1. 检查pom.xml中spring-ai-bom和 starter 依赖。2. 确保Spring Boot版本与Spring AI兼容。3. 运行mvn dependency:tree检查依赖冲突。调用API时返回401 UnauthorizedAPI Key 配置错误或无效。1. 检查application.properties中的api-key。2. 确认API Key是否有余额或权限。3.务必使用环境变量不要硬编码在配置文件中。响应速度非常慢网络问题或模型过大尤其是本地模型。1. 检查网络连接。2. 对于本地模型尝试更小的模型如llama3:8b-phi3:mini。3. 考虑使用流式响应 (chatClient.stream()) 改善用户体验。AI回答内容不符合预期“幻觉”Prompt指令不清晰或上下文不足。1. 优化Prompt给出更明确的角色、格式和约束。2. 采用“思维链”提示要求AI逐步推理。3. 为关键信息提供检索增强RAG减少凭空生成。集成本地模型Ollama不响应Ollama服务未启动或模型未加载。1. 运行ollama list确认模型已下载。2. 运行ollama run model-name确保服务运行。3. 检查spring.ai.openai.base-url是否指向http://localhost:11434。8.2 性能与成本优化建议缓存对相似的AI查询结果进行缓存如使用Redis避免重复调用消耗Token。异步处理对于耗时的AI生成任务使用Async或消息队列如RabbitMQ异步处理避免阻塞HTTP请求。模型选择在效果和成本间权衡。简单任务使用gpt-3.5-turbo复杂推理再用gpt-4。积极评估开源模型。Token管理在Prompt中精简上下文移除不必要的信息。监控API使用量设置预算警报。降级方案当主要AI服务不可用时要有备用的规则引擎或默认回复。8.3 安全与合规最佳实践输入输出过滤对用户输入和AI输出进行严格的审查和过滤防止注入攻击或生成有害内容。隐私保护确保用户输入的个人身份信息PII不被发送给第三方AI服务。必要时进行数据脱敏。审计日志记录所有AI交互的请求和响应便于问题追溯和模型行为分析。人机验证在公开API前加入验证码等机制防止滥用。9. 总结与展望通过本文的实践我们完成了一个从零到一的AI应用搭建从配置Spring AI、集成大模型API到构建一个具备基础推理和工具调用能力的天气助手并进一步探讨了多智能体系统的雏形。这清晰地表明AI工程化的核心并非炒作概念而是扎实的架构设计、清晰的Prompt工程、稳定的服务集成以及对成本与性能的精细把控。对于开发者而言下一步可以深入的方向包括深入Prompt工程学习更高级的提示技巧如Few-shot、Chain-of-Thought。掌握RAG结合向量数据库为AI提供精准的外部知识减少幻觉。探索智能体框架深入研究LangChain、LlamaIndex、AutoGen等框架构建更复杂的自动化工作流。关注模型微调对于特定领域任务收集数据对开源模型进行微调以获得更专业、可控的表现。工程化部署将AI应用容器化Docker并部署到Kubernetes实现弹性伸缩和持续交付。AI技术正在以“基础设施”的姿态融入软件开发的方方面面。作为开发者我们的任务不是恐惧或空谈而是掌握这些强大的工具将其转化为解决实际问题的生产力。从今天开始尝试将一个简单的AI功能集成到你正在开发的项目中那将是迈向AI工程实践最坚实的一步。
返回列表