Java AI 框架选型:LangChain4j 还是 Spring AI?
为什么 Java 开发者需要关注这件事
两年前,大部分 Java 团队面对大模型浪潮的反应是:“我们用 HTTP 调 OpenAI 的 API 不就行了?”
到了 2026 年,如果你还在手写 HttpClient 拼 JSON 调模型接口,说明你还没有遇到真正的复杂度——
- • 当你需要对接多个模型供应商(OpenAI、通义千问、DeepSeek、本地 Ollama)并随时切换时;
- • 当你需要实现 RAG,把企业知识库和大模型结合时;
- • 当你需要 Function Calling,让模型调用你的业务系统时;
- • 当你需要 Agent,让模型自主规划、分步执行任务时。
手写 HTTP 调用的代码会迅速膨胀成难以维护的意大利面条式代码(Spaghetti Code)。而无代码平台(如 Dify、Coze)虽然降低了门槛,但在复杂业务场景中,无法灵活打通系统的各个环节,实现业务的流转和自动化。深入学习编码开发平台依然是 AI 应用开发的核心路径。
框架的价值,就是在这些复杂度面前给你一个经过验证的架构。 Spring AI 的定位正是"连接企业数据与 API 和 AI 模型之间的桥梁"。
本文将深入剖析 Java 生态三大主流 AI 框架:Spring AI、LangChain4j、Semantic Kernel Java,从架构设计、代码实现、生产适用性三个维度给出我的判断。
一、框架全景对比
先上一张总览表,后面逐个拆解:
| 维度 | Spring AI | LangChain4j | Semantic Kernel Java |
|---|---|---|---|
| 出品方 | Broadcom/Spring 官方团队 | 社区驱动 | 微软 |
| Spring Boot 兼容 | 3.5.x(原生集成) | 3.x(通过 langchain4j-spring) | 无原生集成 |
| 模型提供商 | OpenAI、Anthropic、Google、Amazon、Ollama、智谱等 | OpenAI、Anthropic、通义、DeepSeek、智谱、Moonshot 等 20+ 家 | OpenAI、Azure OpenAI、Hugging Face |
| Vector Store 支持 | PGVector、Milvus、Qdrant、Weaviate、Pinecone、Redis、Elasticsearch、Chroma、Neo4j 等 14 种 | PGVector、Milvus、Qdrant、Weaviate、Pinecone、Redis、Elasticsearch 等 | 需自行集成 |
| RAG 支持 | ✅(Advisors 模式) | ✅✅(最完整,含文档加载、分割、检索全链路) | ✅(基础支持) |
| Agent 能力 | 中等(ToolCallAdvisor + MCP 支持) | 较强(Tool + Agent 编排,最成熟) | FunctionChoiceBehavior 引导(Java 版实现不完整) |
| 声明式 API | ❌(命令式 ChatClient) | ✅(AI Services 注解) | ❌ |
| 国内模型支持 | 好(智谱官方集成) | 最好(通义、DeepSeek、智谱、Moonshot 等) | 弱(无官方集成) |
| 学习曲线 | 低(Spring 用户) | 中 | 高 |
| 社区活跃度 | 高 | 高 | 中低 |
| 版本状态 | 正式发布 | 正式发布 | RC1(候选版本) |
二、Spring AI:Spring 生态的自然延伸
架构设计哲学
Spring AI 的设计哲学非常 Spring:约定优于配置,抽象优于实现。
它定义了一套统一的 ChatModel、EmbeddingModel、VectorStore 接口,各个模型提供商通过 starter 提供实现。你只需要在 application.yml 里切换配置,代码一行不改。Spring AI 的目标是将 Spring 生态的设计原则——可移植性、模块化设计、POJO 作为构建块——应用到 AI 领域。
spring.ai.openai.api-key=sk-xxx → OpenAIspring.ai.ollama.base-url=http://... → 本地 Ollamaspring.ai.zhipuai.api-key=xxx → 智谱
核心代码剖析
1. 最简对话 — ChatClient 流式 API
Spring AI 的 ChatClient 提供了流式 API 来与 AI 模型通信,支持同步和流式两种编程模型。
<!-- Maven 依赖(推荐通过 BOM 管理版本) --><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>1.1.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement><dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> <!-- 版本由 BOM 统一管理,无需手写 --></dependency>
``````plaintext
@RestControllerclass MyController { private final ChatClient chatClient; // ChatClient.Builder 是 prototype bean,每次注入创建新实例 public MyController(ChatClient.Builder chatClientBuilder) { this.chatClient = chatClientBuilder .defaultSystem("你是一个专业的Java技术顾问") .build(); } @GetMapping("/ai") String generation(String userInput) { return this.chatClient.prompt() .user(userInput) .call() .content(); }}
在最简单场景下,call() 方法向 AI 模型发送请求,content() 方法以 String 形式返回响应。这是 Spring AI 最核心的交互模式。
2. 多模型切换
Spring AI 支持在同一应用中使用多个 ChatModel。注意: 若需手动创建多个 ChatClient 实例,必须先通过配置项禁用自动配置,否则启动时会产生 Bean 冲突:
# application.ymlspring: ai: chat: client: enabled: false # 禁用自动配置,才能手动注册多个 ChatClient
``````plaintext
@Configurationpublic class ChatClientConfig { // 注意:多模型共存需要在 classpath 上同时添加两个模型的 starter 依赖, // 并在 application.yml 中分别配置各自的 api-key @Bean public ChatClient openAiChatClient(OpenAiChatModel chatModel) { return ChatClient.create(chatModel); } @Bean public ChatClient anthropicChatClient(AnthropicChatModel chatModel) { return ChatClient.create(chatModel); }}
使用 @Qualifier 注入特定实例:
@RestControllerpublic class MultiModelController { private final ChatClient openAiClient; private final ChatClient anthropicClient; public MultiModelController( @Qualifier("openAiChatClient") ChatClient openAiClient, @Qualifier("anthropicChatClient") ChatClient anthropicClient) { this.openAiClient = openAiClient; this.anthropicClient = anthropicClient; }}
3. Prompt 结构化
Spring AI 的 Prompt 类是一个容器,包含一组有序的 Message 对象和请求选项。每条 Message 代表 Prompt 中的一个角色:
- • System Role:引导 AI 的行为和响应风格,在对话开始前提供指令。
- • User Role:代表用户的输入——问题、命令或陈述。
Prompt prompt = new Prompt(List.of( new SystemMessage("你是一个Java架构师,回答要简洁专业"), new UserMessage("Spring Boot 3.x 的 GraalVM 原生镜像支持怎么样?")));ChatResponse response = chatModel.call(prompt);
Prompt 类还提供了便捷方法:getUserMessage() 返回最后一条用户消息,getSystemMessage() 返回第一条系统消息,getUserMessages() 返回所有用户消息列表。
4. RAG 检索增强
Spring AI 通过 Advisors API 实现 RAG,封装了重复的 Generative AI 模式,转换发送给语言模型和从语言模型接收的数据,并在各种模型和用例之间提供可移植性:
@Configurationpublic class RagConfig { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { return new PgVectorStore(jdbcTemplate, embeddingModel); }}@RestControllerpublic class RagController { private final ChatClient chatClient; public RagController(ChatClient.Builder builder, VectorStore vectorStore) { this.chatClient = builder .defaultAdvisors( QuestionAnswerAdvisor.builder(vectorStore).build() ) .build(); } @GetMapping("/rag") public String rag(@RequestParam String question) { return chatClient.prompt() .user(question) .call() .content(); }}
QuestionAnswerAdvisor 是一个拦截器,在每次调用前自动从向量库检索相关文档片段并拼接进 Prompt。整个 RAG 流程对业务代码完全透明。
5. 对话记忆
Spring AI 提供了内置的 MessageChatMemoryAdvisor,无需手动维护会话状态:
import org.springframework.ai.chat.memory.ChatMemory;import org.springframework.ai.chat.memory.ChatMemoryRepository;import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;import org.springframework.ai.chat.memory.MessageWindowChatMemory;import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;@Configurationpublic class MemoryConfig { @Bean public ChatMemoryRepository chatMemoryRepository() { return new InMemoryChatMemoryRepository(); } @Bean public ChatMemory chatMemory(ChatMemoryRepository repository) { // 保留最近 15 轮对话窗口 return MessageWindowChatMemory.builder() .chatMemoryRepository(repository) .maxMessages(15) .build(); }}@RestControllerpublic class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder builder, ChatMemory chatMemory) { this.chatClient = builder .defaultAdvisors( MessageChatMemoryAdvisor.builder(chatMemory).build() ) .build(); } @PostMapping("/chat") public String chat(@RequestParam String sessionId, @RequestParam String message) { return chatClient.prompt() .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId)) .user(message) .call() .content(); }}
Spring AI 的真正优势
1. 零心智负担的 Spring 集成
如果你的项目已经是 Spring Boot,引入 Spring AI 的成本是最低的。Spring AI 支持 Spring Boot 自动配置和 Starters,覆盖所有 AI 模型和向量存储。自动配置、健康检查、可观测性(Observability)全部开箱即用。
2. VectorStore 抽象层设计优秀
Spring AI 支持的向量数据库包括:Apache Cassandra、Azure Vector Search、Chroma、Elasticsearch、Milvus、MongoDB Atlas、MariaDB、Neo4j、Oracle、PostgreSQL/PGVector、Pinecone、Qdrant、Redis、Weaviate 等 14 种。切换向量库只需换依赖和配置,业务代码不用动。
3. 结构化输出(Structured Outputs)
Spring AI 支持将 AI 模型输出直接映射到 POJO,这在需要模型返回结构化数据(如 JSON、实体对象)时非常有用。
4. MCP 支持(1.1.x 新增)
Spring AI 1.1.x 引入了对 Model Context Protocol(MCP)的支持,可以更灵活地接入外部工具和数据源,拓宽了 Agent 能力的边界。Spring AI 团队是 MCP Java SDK 的主要维护者之一,在协议层面的话语权保证了这一集成的长期质量。
Spring AI 的短板
Agent 编排能力仍弱于 LangChain4j。
Spring AI 通过 ToolCallAdvisor 和 Recursive Advisors 提供了基础的 Agent 能力,支持工具调用和简单的自改进循环。但在多工具自动编排、多步推理框架、Agent 任务规划等方面,仍缺乏 LangChain4j 那样成熟的抽象层。Advisors 机制本质上是拦截器模式,而非 Agent 模式,两者在能力上限上有本质差距。在需要复杂 Agent 调度和工具链组合的场景下,Spring AI 可能受限。
不过值得关注的是,Spring AI 2.0 正在这个方向上进行架构级的强化,详见本文第八节的前瞻分析。
三、LangChain4j:功能最全面的 Java AI 框架
架构设计哲学
LangChain4j 的设计理念是:覆盖 AI 应用开发的全部生命周期。
它提供标准化 API,支持 20 余家主流大模型提供商和嵌入存储,从低级提示词模板到高级 AI 服务,适合构建聊天机器人和 RAG 管道。
核心代码剖析
1. 声明式 AI Service(最优雅的设计)
这是 LangChain4j 最让我惊艳的设计。它用 Java 接口 + 注解 的方式定义 AI 能力:
<!-- 推荐使用 BOM 管理版本 --><dependencyManagement> <dependencies> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-bom</artifactId> <version>1.12.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement><dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId></dependency>
``````plaintext
import dev.langchain4j.service.AiServices;import dev.langchain4j.service.SystemMessage;import dev.langchain4j.service.UserMessage;import dev.langchain4j.service.V;public interface TechAssistant { @SystemMessage(""" 你是一个资深Java技术顾问。 回答要简洁、准确,给出代码示例时用Java语言。 如果不确定,明确告知用户。 """) String ask(@UserMessage String question); @SystemMessage("根据以下参考资料回答问题") String ragAsk( @UserMessage String question, @V("context") String context ); @SystemMessage("分析这段Java代码的问题") @UserMessage("请分析以下代码:\n{{code}}") String reviewCode(@V("code") String code);}
使用时:
import dev.langchain4j.model.chat.ChatLanguageModel;import dev.langchain4j.model.openai.OpenAiChatModel;ChatLanguageModel model = OpenAiChatModel.builder() .apiKey("sk-xxx") .modelName("gpt-4o") .temperature(0.3) .build();TechAssistant assistant = AiServices.create(TechAssistant.class, model);// 直接调用,像调用普通 Service 一样String answer = assistant.ask("Java 21 的虚拟线程适合什么场景?");
这个设计的精妙之处在于: 它把 Prompt Engineering 和业务逻辑解耦了。@SystemMessage、@UserMessage、@V 注解负责 Prompt 的组装,业务代码只需要关注"调用哪个接口、传什么参数"。
对比 Spring AI 的命令式调用——Prompt 组装和业务逻辑耦合在一起:
// Spring AI:命令式调用,Prompt 与业务代码写在同处String answer = chatClient.prompt() .system("你是一个Java技术顾问,回答要简洁准确") .user("Java 21 的虚拟线程适合什么场景?") .call() .content();
命令式 vs 声明式的区别:命令式是"在哪里用、怎么拼"写在调用代码里;声明式是把"怎么拼"提升到接口定义层,调用代码只表达"用什么、传什么"。当项目有几十上百个 AI 接口时,声明式方案在可维护性上优势巨大——接口定义即文档,改 Prompt 不需要翻业务代码。
2. 完整的 RAG 流程
LangChain4j 在 RAG 方面提供了最完整的支持——包括文档加载、分割、嵌入、存储、检索和生成的全链路能力:
import dev.langchain4j.data.document.Document;import dev.langchain4j.data.document.DocumentSplitter;import dev.langchain4j.data.document.DocumentSplitters;import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;import dev.langchain4j.data.segment.TextSegment;import dev.langchain4j.model.embedding.EmbeddingModel;import dev.langchain4j.model.openai.OpenAiEmbeddingModel;import dev.langchain4j.rag.content.retriever.ContentRetriever;import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;import dev.langchain4j.store.embedding.EmbeddingStore;import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;import dev.langchain4j.store.embedding.pgvector.PgVectorEmbeddingStore;// Step 1: 文档加载Document document = FileSystemDocumentLoader.loadDocument("docs/architecture.pdf");// Step 2: 文档分割DocumentSplitter splitter = DocumentSplitters.recursive(300, 30);List<TextSegment> segments = splitter.split(document);// Step 3: 向量化 + 存储EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder() .apiKey("sk-xxx") .modelName("text-embedding-3-small") .build();EmbeddingStore<TextSegment> store = PgVectorEmbeddingStore.builder() .host("localhost") .port(5432) .database("ai_db") .table("knowledge") .dimension(1536) .build();EmbeddingStoreIngestor.builder() .embeddingModel(embeddingModel) .embeddingStore(store) .build() .ingest(segments);// Step 4: 检索 + 生成ContentRetriever retriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .maxResults(5) .minScore(0.75) .build();TechAssistant assistant = AiServices.builder(TechAssistant.class) .chatLanguageModel(model) .contentRetriever(retriever) .build();String answer = assistant.ask("Spring Boot 3.x 的 GraalVM 原生镜像支持怎么样?");
3. Tool 工具调用
import dev.langchain4j.agent.tool.Tool;import dev.langchain4j.agent.tool.P;public class DatabaseTool { @Tool("查询用户订单信息,当用户询问订单状态、物流信息时调用") public String queryOrder( @P("用户ID") String userId, @P("订单号,可选") String orderId ) { OrderService orderService = SpringContextHolder.getBean(OrderService.class); List<Order> orders = orderService.queryByUserId(userId, orderId); return JSON.toJSONString(orders); } @Tool("查询商品库存,当用户询问是否有货时调用") public String checkStock(@P("商品SKU") String sku) { InventoryService inv = SpringContextHolder.getBean(InventoryService.class); int stock = inv.getStock(sku); return stock > 0 ? "SKU " + sku + " 库存充足,剩余 " + stock + " 件" : "SKU " + sku + " 已售罄"; }}// 使用TechAssistant assistant = AiServices.builder(TechAssistant.class) .chatLanguageModel(model) .tools(new DatabaseTool()) .build();// 用户说 "我订单 20240315001 到哪了?"// 模型自动识别意图,调用 queryOrder 方法String answer = assistant.ask("我订单 20240315001 到哪了?");
LangChain4j 的 @Tool 注解非常优雅:只需在普通 Java 方法上加一个注解,框架会自动把工具定义转换成模型的 Function Calling Schema,把用户的自然语言意图映射到工具调用,再把返回值回传给模型生成最终回答。
4. 对话记忆
import dev.langchain4j.memory.ChatMemory;import dev.langchain4j.memory.chat.MessageWindowChatMemory;// 内存记忆(开发阶段)ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);TechAssistant assistant = AiServices.builder(TechAssistant.class) .chatLanguageModel(model) .chatMemory(memory) .build();// 或使用 Provider 支持多会话(生产环境)TechAssistant assistant = AiServices.builder(TechAssistant.class) .chatLanguageModel(model) .chatMemoryProvider(sessionId -> MessageWindowChatMemory.builder() .maxMessages(15) .build()) .build();
关于持久化: 如需 Redis 或数据库持久化对话记忆,可实现 ChatMemoryStore 接口自定义存储逻辑。
LangChain4j 的真正优势
1. 声明式 API 是杀手级特性。 在企业级项目中,AI 能力往往需要以 Service 接口的形式暴露给业务层。LangChain4j 的 AiServices 天然适配这种模式,接口即契约,Prompt 即文档。
2. 国内模型支持最全面。 LangChain4j 内置了通义千问(DashScope)、智谱 GLM、Moonshot、DeepSeek、零一万物等国内主流模型的官方集成,这对国内团队是刚需,而不是可选项。
3. Agent 和 Tool 系统成熟度最高。 在复杂 RAG、多步 Agent、工具调用、对 AI 输出流程有高度控制的场景下,LangChain4j 更加灵活,自动处理 tool_calls 循环的能力已相当稳定。
LangChain4j 的不足
1. Spring 集成需要额外工作。 LangChain4j 本质是一个纯 Java 库,虽然提供了 langchain4j-spring-boot-starter 模块,但与 Spring Boot 生态的深度融合(如 Actuator 指标、自动健康检查)不及 Spring AI 原生。
2. 学习曲线较高。 需要理解 AiServices、ChatMemory、ContentRetriever、Tools 等多个核心概念,以及如何将它们组合,对初学者不如 Spring AI 友好。
四、Semantic Kernel Java:值得了解但不建议使用
一个重要说明
在进入代码之前,有必要先点明这个版本号后缀的含义:当前 Java 版本仍是候选版本(RC1),尚未正式发布。与之相比,Spring AI 和 LangChain4j 均是正式发布的稳定版本。这一差距会贯穿你在 Semantic Kernel Java 上的整个使用体验。
架构设计哲学
Semantic Kernel 的核心概念是 Kernel(内核)+ Plugins(插件)+ Planners(规划器)。它的设计起源于微软的 C# 技术栈,强调企业级安全、可观测性和插件化架构。Java 版本是后续移植的产物,这一背景深刻影响了其 API 风格。
核心代码剖析
1. 构建 Kernel + 对话
<dependency> <groupId>com.microsoft.semantic-kernel</groupId> <artifactId>semantickernel-api</artifactId> <version>1.4.4-RC1</version></dependency><dependency> <groupId>com.microsoft.semantic-kernel</groupId> <artifactId>semantickernel-aiservices-openai</artifactId> <version>1.4.4-RC1</version></dependency>
``````plaintext
import com.microsoft.semantickernel.Kernel;import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;// 构建 Chat Completion 服务Kernel kernel = Kernel.builder() .withAIService(ChatCompletionService.class, OpenAIChatCompletion.builder() .withModelId("gpt-4o") .withApiKey("sk-xxx") .build()) .build();// 构建对话历史ChatHistory chatHistory = new ChatHistory();chatHistory.addSystemMessage("你是一个专业的Java技术顾问");chatHistory.addUserMessage("Java 21 的虚拟线程适合什么场景?");// 调用(Reactor 响应式风格)List<ChatMessageContent<?>> response = kernel.getService(ChatCompletionService.class) .getChatMessageContentsAsync(chatHistory, kernel, null) .block();String answer = response.get(0).getContent();
注意: Maven 依赖中保留版本号是必要的——Semantic Kernel Java 尚未发布正式版,无法通过 Spring BOM 或 Maven Central 的版本推导自动获取,必须手动指定。
2. Plugin 定义(类似 Function Calling)
import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;public class WeatherPlugin { @DefineKernelFunction(name = "getWeather", description = "获取指定城市的天气信息") public String getWeather( @KernelFunctionParameter(name = "city", description = "城市名称") String city ) { return city + "今天晴,25°C"; } @DefineKernelFunction(name = "searchFlights", description = "查询航班信息") public String searchFlights( @KernelFunctionParameter(name = "from", description = "出发城市") String from, @KernelFunctionParameter(name = "to", description = "到达城市") String to ) { return from + "到" + to + "的航班:CA1234 08:00, MU5678 14:30"; }}// 注册 PluginKernelPlugin weatherPlugin = KernelPluginFactory .createFromObject(new WeatherPlugin(), "Weather");Kernel kernel = Kernel.builder() .withAIService(ChatCompletionService.class, chatCompletion) .withPlugin(weatherPlugin) .build();
3. 关于工具调用与 Planner 功能的重要说明
当前版本新增了 FunctionChoiceBehavior,用于替代旧版的 ToolCallBehavior,引导模型调用插件中的函数。这是相比上一个版本的重要 API 变化,如果你基于旧版文档编写代码,请注意迁移。
然而,C# 版本中亮眼的 HandlebarsPlanner 和 SequentialPlanner 功能在 Java 版本中仍未完整实现。Java 版本目前支持基础的 FunctionChoiceBehavior 来引导模型调用工具,但尚无等同于 C# 版 Planner 的 Java 稳定实现,多步工具链的自动编排仍需开发者手动处理。
这是 Java 版本与 C# 版本最显著的功能 gap 之一。如果你基于网上或官方文档的 C# 示例直接翻译成 Java 代码,会发现相关类根本不存在,请务必注意这一陷阱。
Semantic Kernel Java 的问题
1. Java 版本是 C# 版本的二等公民,且仍处于 RC 阶段。 Semantic Kernel 的 C# 版本是微软亲自维护的旗舰实现,功能迭代快、文档完善、社区活跃。Java 版本属于后续移植,功能持续滞后,部分特性延迟数个月甚至更长时间才出现在 Java 端,且版本至今仍是 RC 状态。
2. API 设计不够 Java 化。getChatMessageContentsAsync(...).block() 这种风格带有浓厚的 C# 异步编程(Reactive Extensions)痕迹,在 Java 生态中显得格格不入。相比之下,LangChain4j 的 assistant.ask("hello") 和 Spring AI 的 chatClient.prompt().call().content() 都更符合 Java 开发者的直觉。
3. 国内模型支持几乎为零。 没有内置的通义千问、DeepSeek 等集成,在国内环境下基本不可用。
4. 社区活跃度明显偏低。 在 GitHub Star 数量、Issue 响应速度、第三方教程资源等维度,Java 版本的 Semantic Kernel 都远落后于 Spring AI 和 LangChain4j。遇到问题时难以从社区获得及时的支持。
五、Spring AI vs LangChain4j 代码级对比
说明: 本节聚焦 Spring AI 和 LangChain4j 这两个社区最活跃、生产适用性最高的框架进行代码级对比。Semantic Kernel Java 因版本仍处于 RC 状态、社区活跃度低、国内模型支持不足,不在本次对比之列(详见第四节分析)。
5.1 构建同一个 RAG 应用的代码量对比
假设需求:构建一个企业知识库问答系统,支持 PDF 文档导入、向量检索、对话记忆。
Spring AI 版本
import org.springframework.ai.chat.memory.ChatMemory;import org.springframework.ai.chat.memory.ChatMemoryRepository;import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;import org.springframework.ai.chat.memory.MessageWindowChatMemory;import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;@Servicepublic class KnowledgeService { private final ChatClient chatClient; private final VectorStore vectorStore; public KnowledgeService(ChatClient.Builder builder, VectorStore vectorStore, ChatMemoryRepository memoryRepository) { this.vectorStore = vectorStore; ChatMemory chatMemory = MessageWindowChatMemory.builder() .chatMemoryRepository(memoryRepository) .maxMessages(15) .build(); this.chatClient = builder .defaultAdvisors( QuestionAnswerAdvisor.builder(vectorStore).build(), MessageChatMemoryAdvisor.builder(chatMemory).build() ) .build(); } public void ingestPdf(String filePath) { var reader = new PagePdfDocumentReader(filePath); var splitter = new TokenTextSplitter(300, 50); var documents = reader.get(); var segments = splitter.apply(documents); vectorStore.add(segments); } public String ask(String sessionId, String question) { return chatClient.prompt() .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId)) .user(question) .call() .content(); }}
LangChain4j 版本
import dev.langchain4j.service.AiServices;import dev.langchain4j.service.SystemMessage;import dev.langchain4j.service.UserMessage;import dev.langchain4j.memory.ChatMemory;import dev.langchain4j.memory.chat.MessageWindowChatMemory;import dev.langchain4j.rag.content.retriever.ContentRetriever;import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;public interface KnowledgeAssistant { @SystemMessage(""" 你是企业知识库助手。根据参考资料回答问题。 如果参考资料中没有相关内容,明确告知用户。 回答要专业、简洁,引用具体章节。 """) String ask(@UserMessage String question);}@Servicepublic class KnowledgeService { private final KnowledgeAssistant assistant; private final EmbeddingStore<TextSegment> store; public KnowledgeService() { this.store = PgVectorEmbeddingStore.builder() .host("localhost") .port(5432) .database("ai_db") .table("knowledge") .dimension(1536) .build(); EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder() .apiKey("sk-xxx") .modelName("text-embedding-3-small") .build(); ContentRetriever retriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .maxResults(5) .minScore(0.7) .build(); ChatMemory memory = MessageWindowChatMemory.withMaxMessages(15); ChatLanguageModel model = OpenAiChatModel.builder() .apiKey("sk-xxx") .modelName("gpt-4o") .temperature(0.3) .build(); this.assistant = AiServices.builder(KnowledgeAssistant.class) .chatLanguageModel(model) .contentRetriever(retriever) .chatMemory(memory) .build(); } public void ingestPdf(String filePath) { Document document = FileSystemDocumentLoader.loadDocument(filePath); DocumentSplitter splitter = DocumentSplitters.recursive(300, 30); List<TextSegment> segments = splitter.split(document); EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder() .apiKey("sk-xxx") .modelName("text-embedding-3-small") .build(); EmbeddingStoreIngestor.builder() .embeddingModel(embeddingModel) .embeddingStore(store) .build() .ingest(segments); } public String ask(String question) { return assistant.ask(question); }}
对比感受:
| 维度 | Spring AI | LangChain4j |
|---|---|---|
| 代码行数 | ~45 行 | ~55 行 |
| 对话记忆 | Advisor 内置,几行配置 | 框架内置,一行配置 |
| Prompt 管理 | 混在业务代码中 | 注解声明,与业务解耦 |
| 可维护性 | 接口多了以后会乱 | 接口定义即文档 |
| Spring 生态集成 | 原生无缝 | 需额外配置 |
Spring AI 在快速启动、与已有 Spring 项目整合方面更优;LangChain4j 在 Prompt 组织、复杂控制、自定义 RAG 服务方面更灵活。当前版本的两个框架在对话记忆的易用性上已趋于一致,Spring AI 通过 MessageChatMemoryAdvisor 补齐了这一短板。
5.2 构建同一个 Agent 应用的对比
假设需求:构建一个能自动查天气、查航班、预订酒店的旅行助手 Agent。
LangChain4j 版本
import dev.langchain4j.agent.tool.Tool;import dev.langchain4j.agent.tool.P;public class TravelTools { @Tool("查询城市天气") public String getWeather(@P("城市名") String city) { return WeatherService.query(city); } @Tool("查询航班信息") public String searchFlights( @P("出发城市") String from, @P("到达城市") String to, @P("日期,格式 yyyy-MM-dd") String date ) { return FlightService.search(from, to, date); } @Tool("预订酒店") public String bookHotel( @P("城市名") String city, @P("入住日期") String checkIn, @P("退房日期") String checkOut, @P("房间类型") String roomType ) { return HotelService.book(city, checkIn, checkOut, roomType); }}TravelAssistant assistant = AiServices.builder(TravelAssistant.class) .chatLanguageModel(model) .tools(new TravelTools()) .build();// 框架自动处理整个 tool_calls 循环:// 1. 调用 getWeather("上海")// 2. 调用 searchFlights("当前城市", "上海", "2026-03-26")// 3. 调用 bookHotel("上海", "2026-03-26", "2026-03-28", "商务房")// 4. 综合结果生成最终回答String answer = assistant.chat("我下周三要去上海出差,帮我查下天气和航班,订个商务房");
Spring AI 版本
Spring AI 支持方法级 @Tool 注解,无需定义额外的 Request/Response DTO:
import org.springframework.ai.tool.annotation.Tool;import org.springframework.ai.tool.annotation.ToolParam;@Componentpublic class TravelTools { @Tool(description = "查询城市天气") public String getWeather(@ToolParam(description = "城市名称") String city) { return WeatherService.query(city); } @Tool(description = "查询航班信息") public String searchFlights( @ToolParam(description = "出发城市") String from, @ToolParam(description = "到达城市") String to, @ToolParam(description = "日期,格式 yyyy-MM-dd") String date ) { return FlightService.search(from, to, date); } @Tool(description = "预订酒店") public String bookHotel( @ToolParam(description = "城市名称") String city, @ToolParam(description = "入住日期") String checkIn, @ToolParam(description = "退房日期") String checkOut, @ToolParam(description = "房间类型") String roomType ) { return HotelService.book(city, checkIn, checkOut, roomType); }}@RestControllerpublic class TravelController { private final ChatClient chatClient; public TravelController(ChatClient.Builder builder, TravelTools travelTools) { this.chatClient = builder .defaultTools(travelTools) .build(); } @PostMapping("/travel") public String travel(@RequestBody String message) { return chatClient.prompt() .user(message) .call() .content(); }}
Semantic Kernel Java 版本
import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;public class TravelPlugin { @DefineKernelFunction(name = "getWeather", description = "查询城市天气") public String getWeather( @KernelFunctionParameter(name = "city", description = "城市名") String city ) { return WeatherService.query(city); } @DefineKernelFunction(name = "searchFlights", description = "查询航班信息") public String searchFlights( @KernelFunctionParameter(name = "from", description = "出发城市") String from, @KernelFunctionParameter(name = "to", description = "到达城市") String to, @KernelFunctionParameter(name = "date", description = "日期") String date ) { return FlightService.search(from, to, date); } @DefineKernelFunction(name = "bookHotel", description = "预订酒店") public String bookHotel( @KernelFunctionParameter(name = "city", description = "城市名") String city, @KernelFunctionParameter(name = "checkIn", description = "入住日期") String checkIn, @KernelFunctionParameter(name = "checkOut", description = "退房日期") String checkOut, @KernelFunctionParameter(name = "roomType", description = "房间类型") String roomType ) { return HotelService.book(city, checkIn, checkOut, roomType); }}// 注册 Plugin(当前版本以 FunctionChoiceBehavior 替代旧版 ToolCallBehavior)KernelPlugin travelPlugin = KernelPluginFactory .createFromObject(new TravelPlugin(), "Travel");Kernel kernel = Kernel.builder() .withAIService(ChatCompletionService.class, chatCompletion) .withPlugin(travelPlugin) .build();// 注意:Java 版本暂无等同 C# HandlebarsPlanner 的自动编排实现。// 当前可通过 FunctionChoiceBehavior 配置引导模型调用工具,// 但仍需开发者手动处理多轮 tool_calls 循环,比 LangChain4j 繁琐许多。
三个框架的 Agent 实现对比:
| 维度 | Spring AI | LangChain4j | Semantic Kernel Java |
|---|---|---|---|
| 定义工具 | 方法 + @Tool + @ToolParam |
方法 + @Tool + @P |
方法 + @DefineKernelFunction |
| 需要 DTO 类 | ❌ 不需要 | ❌ 不需要 | ❌ 不需要 |
| 自动处理 tool_calls 循环 | ✅ 框架自动处理 | ✅ 框架自动处理 | ⚠️ 需手动处理 |
| 自动多步编排(Planner) | ❌ 无 | ✅ 框架自动处理 | ⚠️ Java 版尚未完整实现 |
| 代码量 | 较少 | 最少 | 最多 |
| API 可读性 | 好 | 最好 | 较差(注解冗长,风格偏 C#) |
从这张表可以看出,Spring AI 和 LangChain4j 在工具定义层面已经非常接近,主要差距落在多步 Agent 自动编排上。LangChain4j 的框架会自动处理完整的 tool_calls 循环直到模型生成最终回答,而 Spring AI 在这方面的实现目前仍有差距。Semantic Kernel Java 版本的 Agent 能力受限于移植进度,对 Java 开发者并不友好。
六、我的判断:不是中立,是结论
经过对三个框架的架构分析、代码实践和生产验证,我的判断如下:
🥇 首选:LangChain4j
适用场景:绝大多数 Java AI 应用开发。
理由:
- 声明式 API 是面向未来的架构选择。 当 AI 能力在项目中从 1 个接口增长到 50 个接口时,LangChain4j 的
AiServices注解方案在可维护性上碾压命令式调用。接口定义即文档,Prompt 改动不需要翻业务代码。 - 功能完整度最高。 RAG、Agent、Tool Calling、对话记忆、Guardrails、文档加载器——你需要的东西它都有,而且质量不差。
- 国内模型支持最好。 通义千问(DashScope)、DeepSeek、智谱 GLM、Moonshot 都有官方集成,这对于国内团队是刚需,而不是可选项。
- 社区活跃度高,迭代快。 遇到问题能在 GitHub Issues 中找到答案,新功能的响应速度也快,正式版本稳定可靠。
🥈 次选:Spring AI
适用场景:已有 Spring Boot 项目,需要快速、轻量地接入大模型能力,且业务复杂度以 RAG 和基础工具调用为主。
理由:
- Spring 生态的无缝集成不可替代。 如果你的项目深度依赖 Spring 的自动配置、Actuator 监控、Security 安全框架,Spring AI 的集成成本最低,Observability 等企业级特性开箱即用。
- VectorStore 抽象层设计优秀。 统一的接口 + 14 种向量库实现,切换向量库时业务代码不用动。
- 核心短板已在当前版本补齐。 内置的
MessageChatMemoryAdvisor解决了对话记忆管理的问题,方法级@Tool注解也解决了工具定义繁琐的历史问题。 - 但多步 Agent 编排仍是瓶颈。 一旦需求升级到"多工具自主规划 + 多步推理",Spring AI 的能力上限仍不及 LangChain4j。这是选择两者的核心判断依据。而随着 Spring AI 2.0 的成熟,这一差距有望缩小,详见下一章节。
🥉 不推荐:Semantic Kernel Java
适用场景:几乎没有。除非公司强制要求微软技术栈,或团队主体是从 C# 迁移到 Java。
理由:
- Java 版本是 C# 版本的二等公民,且仍处于 RC 阶段。 功能持续滞后,Planner 等核心特性在 Java 端尚未完整实现。
- API 设计不符合 Java 开发者的习惯。 大量
.block()调用和冗长注解让代码维护成本居高不下。 - 国内模型支持为零。 在中国云环境下几乎不可用。
- 社区生态与另外两者差距悬殊。 遇到问题时难以获得及时的社区支持,第三方资料也极为匮乏。
七、最佳实践:推荐技术栈
对于一个新启动的 Java AI 应用项目,我的推荐技术栈是:
<!-- Spring Boot 基础 --><parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.5.6</version></parent><!-- LangChain4j BOM:统一管理所有 langchain4j 模块版本,避免冲突 --><dependencyManagement> <dependencies> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-bom</artifactId> <version>1.12.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement><!-- LangChain4j Spring Boot 集成 --><dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-spring-boot-starter</artifactId></dependency><!-- 模型提供商(按需选择其一或多个) --><dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId></dependency><dependency> <!-- 国内:通义千问 / DashScope --> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId></dependency><!-- 向量数据库 --><dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-pgvector</artifactId></dependency><!-- 文档解析 --><dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-document-parser-apache-pdfbox</artifactId></dependency>
提示: 通义千问(DashScope)在 LangChain4j 1.x 中已迁移至社区模块,artifact 为
langchain4j-community-dashscope-spring-boot-starter。旧版的langchain4j-dashscope-spring-boot-starter是 0.x 时代的命名,已不适用于当前版本。
# application.ymllangchain4j: open-ai: chat-model: api-key: ${OPENAI_API_KEY} model-name: gpt-4o temperature: 0.3 max-tokens: 2048 embedding-model: api-key: ${OPENAI_API_KEY} model-name: text-embedding-3-small
``````plaintext
# 推荐项目结构├── assistant/│ ├── TechAssistant.java // 声明式 AI 接口│ ├── KnowledgeAssistant.java // RAG 知识库助手│ └── CodeReviewAssistant.java // 代码审查助手├── tool/│ ├── DatabaseTool.java // 数据库查询工具│ ├── HttpTool.java // 外部 API 调用工具│ └── FileTool.java // 文件操作工具├── rag/│ ├── DocumentIngestService.java // 文档导入服务│ └── RagConfig.java // RAG 配置├── memory/│ └── ChatMemoryConfig.java // 对话记忆配置└── controller/ ├── ChatController.java // 对话接口 └── IngestController.java // 文档导入接口
这套结构的核心思路是:assistant/ 层只放声明式 AI 接口,任何人看到接口签名就能理解它的职责;tool/ 层放工具实现,与 AI 接口解耦;rag/ 层管理知识库相关的配置和流程。业务层通过 @Autowired 注入 assistant/ 下的接口,对 AI 框架的细节完全无感。
八、前瞻:Spring AI 2.0 将带来什么
本文主体内容基于 Spring AI 1.1.3 撰写,但 Spring AI 2.0 的里程碑版本已在进行中,其变化幅度足以影响框架选型的判断——尤其是对 Spring AI 最大短板"Agent 能力"的评价。核心影响是:Spring AI 2.0 正在通过生态系统化的方式补齐 Agent 能力短板,了解 2.0 的方向,有助于在规划长期技术栈时做出更有前瞻性的决策。
8.1 核心平台升级:Spring Boot 4 + Spring Framework 7
Spring AI 2.0.0-M1 是 2.x 系列的第一个里程碑,发布于 2025 年 12 月 11 日。2.0.0-M3 于 2026 年 3 月 16 日与 1.1.3 正式版同期发布,基于 Spring Boot 4.0 GA 和 Spring Framework 7.0 构建,以 Jakarta EE 11 为新基线。这不是一次普通的版本号递进,而是一次底层平台的代际迭代。
Jakarta EE 11 带来了为 Java 21 构建的 16 个更新规范,包括 Jakarta Concurrency 3.1 中的虚拟线程支持,以及整个技术栈中的 Records 支持。对 AI 应用而言,虚拟线程的意义尤为重要:当你需要并发编排数十个 LLM 调用时,传统线程池很容易成为瓶颈,而虚拟线程能以极低的开销支撑大规模并发,这对高吞吐量的 AI 推理服务是实质性的提升。
版本进展:
- • 2.0.0-M1(2025 年 12 月 11 日):首个里程碑,67 个改进和修复
- • 2.0.0-M2(2026 年 1 月 23 日):94 个变更——36 个改进、16 个 bug 修复、38 个文档更新、4 个依赖升级
- • 2.0.0-M3(2026 年 3 月 16 日):与 1.1.3 正式版同期发布,包含重要的破坏性变更
值得注意的是,2.0.0-M3 包含若干破坏性变更,包括 MCP 注解包重命名(从 org.springaicommunity.mcp 迁移至 org.springframework.ai.mcp.annotation)、MCP 传输工件迁移、Jackson 2 升级至 Jackson 3,以及从 ToolContext 中移除对话历史。如果你打算从 1.x 迁移到 2.0,升级前务必仔细阅读官方 Upgrade Notes。
8.2 Agent 生态:从框架到生态系统
Spring AI 2.0 在 Agent 方向最值得关注的,不只是框架本身的增强,而是围绕它形成的生态系统正在快速成型。
Embabel:Spring 创始人亲自操刀的 Agent 框架
Embabel Agent Framework 由 Spring Framework 创始人 Rod Johnson 创建,旨在通过在 Spring AI 之上提供更高层级的抽象,简化 JVM 上 AI Agent 的构建。它于 2025 年 6 月首次发布,目前版本为 0.3.x。
Embabel 的核心思路是引入目标导向行动规划(GOAP)算法:Agent 由强类型的动作、目标和领域模型组成,当假设条件发生变化或某个步骤失败时,执行路径可以动态重新规划,使 Agent 行为保持可解释性、确定性和可测试性。
Embabel 构建于 Spring AI 之上,拥抱 Spring 组件模型,但定位上更像是 Spring AI 的上层框架:Spring AI 类似于 Servlet API 层面,而 Embabel 更像 Spring MVC——复杂需求用 Embabel 比直接使用 Spring AI 更易于表达和测试。
这个类比非常准确。如果你已经在用 Spring AI,Embabel 是将 Agent 能力推向生产级可靠性的自然延伸,而无需更换基础框架。
MCP 生态的深化
Spring AI 2.0 重点强化了 MCP(Model Context Protocol)支持,包括将 MCP 注解从社区模块合并入 Spring AI 核心的 org.springframework.ai.mcp.annotation 包,以及面向企业认证合规的 MCP Security。Spring AI 团队也是 MCP Java SDK 的主要维护者,这意味着在协议演进层面,Spring AI 2.0 将始终保持第一梯队的响应速度。
Agent2Agent(A2A)协议支持
Spring AI 正在推进对 Agent2Agent(A2A)协议的集成,这是一个用于 AI Agent 之间无缝通信的开放标准,使 Agent 能够跨平台发现能力、交换消息、协调工作流。2026 年 1 月 29 日,Spring 官方博客发布了关于 A2A 集成的详细指南。当企业 AI 系统从单 Agent 走向多 Agent 协作时,A2A 协议的重要性将快速凸显。
8.3 空指针安全(Null Safety)
这是一个容易被忽视但对企业级开发很有价值的特性。Spring AI 2.0 整个代码库正在迁移到 JSpecify,通过 NullAway 在编译期强制执行空值安全,对 Kotlin 用户而言将转化为真正的可空类型支持。这在大型团队协作和长期维护的项目中能显著减少运行时 NPE。
8.4 对选型判断的影响
综合以上变化,Spring AI 2.0 正在做的事情,是将 1.x 版本的短板——Agent 编排薄弱——通过生态系统化的方式补齐:框架本身专注做好底层抽象和 MCP 集成,Agent 编排的上层能力交给 Embabel 这样的专项框架来承载。
这个分层策略是合理的,但也意味着当前(2026 年上半年)Spring AI 2.0 尚处于 Milestone 阶段,生产项目不应直接升级。待 2.0 正式 GA、Embabel 完成稳定版本发布后,Spring AI + Embabel 的组合将在 Agent 场景下与 LangChain4j 形成真正意义上的竞争。
如果你的项目预计在 2026 年下半年或更晚才进入 Agent 阶段的重度使用,并且团队对 Spring 生态有强烈偏好,值得持续关注 2.0 的进展,并在技术选型中为这条路线保留空间。
写在最后
框架选型不是信仰之争。Spring AI 有它的舒适区,Semantic Kernel 有它的适用场景,但如果你问我 “现阶段,Java 团队做 AI 应用应该选什么”,我的答案是:
LangChain4j。
不是因为它完美,而是因为它的声明式架构设计、功能完整度和国内生态支持这三件事同时做到位了。在 AI 应用从 PoC 走向生产的过程中,这三点决定了你的代码是越写越优雅,还是越写越难维护。
如果你的项目已深度依赖 Spring,不想引入额外的学习和集成成本,Spring AI 也是一个扎实的选择——但要清楚它在复杂 Agent 编排上的当前天花板,同时密切关注 Spring AI 2.0 + Embabel 组合的成熟进度,在合适的时机评估升级路径。
框架选错了可以换,但架构选错了,重构的代价是乘法级的。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)