Semantic Kernel 在 Java 里的使用——微软这个框架值得学吗
Semantic Kernel 在 Java 里的使用——微软这个框架值得学吗
适读人群:Java 技术栈的 AI 应用开发者 | 阅读时长:约 14 分钟 | 核心价值:Semantic Kernel Java 版的真实使用体验,与 Spring AI 和 LangChain4j 的深度对比,给出明确的选型建议
我当时看到微软出 Semantic Kernel 的 Java 版,第一反应是:微软在 Java 生态做 AI 框架?这操作有点反直觉,想看看做得怎么样。
结果花了一个星期认真评测,结论出乎我意料:它做得比我想象的认真,有一些设计思路比 Spring AI 和 LangChain4j 都先进,但也有一些地方明显是"移植 C# 版"的痕迹,用 Java 原生开发者的视角看有些不适应。
这篇文章把评测过程写出来,给你一个明确的结论:什么情况下值得选它。
背景:Java 生态里的 AI 框架现状
在讲 Semantic Kernel 之前,先把 Java 生态里的主要选项说清楚:
Spring AI: Spring 官方出的 AI 集成框架。优点是和 Spring Boot 生态无缝集成,文档完善,社区活跃。缺点是相对较新,某些高级特性还在快速演进中。
LangChain4j: 把 Python LangChain 的概念移植到 Java。优点是功能全面,有大量工具集成。缺点是抽象层次重,有时候代码量比直接调 SDK 还多。
Semantic Kernel Java: 微软官方维护的 Java 版本,核心设计和 C#/Python 版本一致。
这三个框架都能做 AI 应用,定位有重叠,但侧重点不同。
Semantic Kernel 的核心设计思路
Semantic Kernel 有几个核心概念,先理解这些才能评价它的设计是否合理:
Kernel(核心对象): 所有功能的入口,集成 LLM 服务、插件、内存等。
Plugin(插件): 功能模块,对应 LangChain 里的 Tool。但 Semantic Kernel 的插件概念更结构化,一个插件可以包含多个函数,函数有明确的输入输出描述。
KernelFunction: 可以是 Java 方法(用注解标记),也可以是 Prompt 模板。这个设计我觉得是 Semantic Kernel 最聪明的地方——代码函数和 Prompt 函数统一对待。
Planner(规划器): 自动把用户目标分解成步骤,调用合适的插件完成任务。这个功能很强,但也不稳定。
代码对比:同一个任务,三个框架怎么写
任务: 构建一个 Agent,能搜索新闻、分析情绪、生成摘要。
Spring AI 实现
// Spring AI 方式
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
@Component
public class NewsAnalysisAgent {
private final ChatClient chatClient;
public NewsAnalysisAgent(ChatModel chatModel) {
this.chatClient = ChatClient.builder(chatModel)
.defaultSystem("""
你是一个新闻分析助手。
你有以下工具:searchNews(搜索新闻)、analyzeSentiment(情绪分析)。
根据用户请求,使用合适的工具完成任务。
""")
.build();
}
public String analyze(String userRequest) {
return chatClient.prompt()
.user(userRequest)
.tools(new NewsTools()) // 工具类
.call()
.content();
}
// 工具定义
static class NewsTools {
@Tool(description = "搜索相关新闻,参数 query 是搜索关键词")
public String searchNews(String query) {
// 实际接搜索 API
return "[模拟] 找到关于 " + query + " 的3条新闻:新闻1、新闻2、新闻3";
}
@Tool(description = "分析文本情绪,返回 positive/negative/neutral")
public String analyzeSentiment(String text) {
// 实际可以调用专门的情绪分析 API
return "positive";
}
}
}Spring AI 的代码很 Spring,写起来很顺手,和 Spring Boot 项目完全融合。
LangChain4j 实现
// LangChain4j 方式
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
public class NewsAnalysisAgentLC4J {
// 定义 AI 服务接口
interface NewsAnalyst {
@SystemMessage("""
你是一个新闻分析助手。
使用可用工具完成新闻搜索和分析任务。
""")
String analyze(String userRequest);
}
// 工具类
static class NewsToolsLC4J {
@Tool("搜索相关新闻,query 是搜索关键词")
public String searchNews(String query) {
return "[模拟] 找到关于 " + query + " 的3条新闻:新闻1、新闻2、新闻3";
}
@Tool("分析文本情绪")
public String analyzeSentiment(String text) {
return "positive";
}
}
public static void main(String[] args) {
var model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
.build();
var analyst = AiServices.builder(NewsAnalyst.class)
.chatLanguageModel(model)
.tools(new NewsToolsLC4J())
.build();
String result = analyst.analyze("分析最近关于 AI 的重要新闻");
System.out.println(result);
}
}LangChain4j 的接口代理方式很优雅,类型安全,但在复杂场景下配置链很麻烦。
Semantic Kernel 实现
// Semantic Kernel 方式
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.orchestration.InvocationContext;
import com.microsoft.semantickernel.plugin.KernelPlugin;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;
import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
public class NewsAnalysisAgentSK {
// 插件定义:使用注解,比 LangChain4j 更明确的类型系统
public static class NewsPlugin {
@DefineKernelFunction(
name = "searchNews",
description = "搜索相关新闻",
returnDescription = "新闻标题和摘要列表"
)
public String searchNews(
@KernelFunctionParameter(name = "query", description = "搜索关键词") String query
) {
return "[模拟] 找到关于 " + query + " 的3条新闻:新闻1、新闻2、新闻3";
}
@DefineKernelFunction(
name = "analyzeSentiment",
description = "分析文本情绪,返回 positive/negative/neutral",
returnDescription = "情绪分类结果"
)
public String analyzeSentiment(
@KernelFunctionParameter(name = "text", description = "待分析文本") String text
) {
return "positive";
}
}
public static void main(String[] args) {
// 初始化 OpenAI 客户端(SK 用 openai-java SDK)
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 构建 ChatCompletion 服务
ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
.withOpenAIClient(openAIClient)
.withModelId("gpt-4o-mini")
.build();
// 注册插件
KernelPlugin newsPlugin = KernelPluginFactory.createFromObject(
new NewsPlugin(), "NewsPlugin"
);
// 构建 Kernel
Kernel kernel = Kernel.builder()
.withAIService(ChatCompletionService.class, chatCompletionService)
.withPlugin(newsPlugin)
.build();
// 调用(这里是简单调用,SK 还有 Planner 自动规划)
var chatHistory = new com.microsoft.semantickernel.services.chatcompletion.ChatHistory();
chatHistory.addSystemMessage("""
你是一个新闻分析助手。
使用可用工具完成新闻搜索和分析任务。
""");
chatHistory.addUserMessage("分析最近关于 AI 的重要新闻");
var result = chatCompletionService
.getChatMessageContentsAsync(
chatHistory,
kernel,
InvocationContext.builder()
.withToolCallBehavior(
com.microsoft.semantickernel.orchestration.ToolCallBehavior.allowAllKernelFunctions(true)
)
.build()
)
.block();
result.forEach(msg -> System.out.println(msg.getContent()));
}
}Semantic Kernel 的真实优势
优势一:插件的元数据更丰富
@DefineKernelFunction 注解支持 returnDescription,这是 Spring AI 和 LangChain4j 目前不支持的。返回值的描述能帮助 LLM 更好地理解工具输出的含义,在复杂的工具链里差异明显。
优势二:Prompt Function 和 Code Function 统一
Semantic Kernel 允许你把 Prompt 模板也注册为 KernelFunction,和 Java 方法一样被调用:
// 把 Prompt 当函数用
String promptTemplate = """
分析以下新闻的核心要点:
{{$news_content}}
输出格式:
- 核心事件:
- 影响分析:
- 行动建议:
""";
var summarizeFunction = KernelFunctionFromPrompt.create(promptTemplate);
// 调用 Prompt Function(和调用 Java 方法一样的方式)
var result = kernel.invokeAsync(summarizeFunction)
.withVariable("news_content", newsText)
.block();这种设计让 Prompt 管理更结构化,特别是当你有大量 Prompt 模板需要管理时。
优势三:多语言生态一致性
如果你的团队同时有 C#、Python、Java 工程师,Semantic Kernel 三种语言的概念和 API 设计高度一致,可以共享知识、共享 Prompt 模板(存储格式相同)。这对微软生态的企业很有价值。
Semantic Kernel 的问题
问题一:Java 版功能滞后于 C# 版
我评测时(2025 年 Q1),Java 版的 Planner 功能比 C# 版落后 2-3 个月,某些新特性在 Java 版里还没实现。如果你需要用最新的 SK 功能,Java 不是最佳选择。
问题二:初始化代码量明显偏多
对比上面三个框架的代码,Semantic Kernel 的初始化部分最长。每次创建 Kernel 都要写一大串 builder 链,和 Spring 的自动配置比起来,开发体验差一些。
问题三:响应式编程(.block())的不适感
SK Java 版用了 Project Reactor,内部都是响应式 API(返回 Mono<T>),但大多数 Java Web 项目是命令式编程,到处加 .block() 非常丑,也容易在响应式上下文里产生死锁。
问题四:社区和文档比 Spring AI 差
中文文档几乎没有,英文文档有但不完整,Stack Overflow 上的 SK Java 相关问题答案很少。遇到问题,只能查源码或者去 GitHub issues 里找。
明确的选型建议
选 Spring AI 的场景:
- 你的项目本来就是 Spring Boot 技术栈
- 团队熟悉 Spring 生态
- 需要快速开发,不想花太多时间学习新框架
- 这是大多数 Java 企业项目的最优解
选 LangChain4j 的场景:
- 需要用大量 LangChain 生态的工具和集成
- 熟悉 Python LangChain,想要近似的 Java 体验
- 需要复杂的 RAG 流程管理
选 Semantic Kernel 的场景:
- 你的项目是微软技术栈(Azure、.NET 系),SK 和 Azure AI 服务的集成最完善
- 团队同时有 C# 和 Java 工程师,要在两个语言间保持 AI 能力的一致性
- 需要丰富的 Prompt Function 管理,把 Prompt 当代码一样管理版本
- 企业内部有 Semantic Kernel 的 C# 积累,Java 新服务想复用这套体系
不推荐 Semantic Kernel 的场景:
- 纯 Java / Spring 技术栈,没有微软生态
- 对响应式编程不熟悉,不想处理
.block()的问题 - 需要用 SK 最新特性(Java 版会有延迟)
我的最终判断
Semantic Kernel Java 版是一个"认真做出来的框架,但目标用户很具体"的产品。
如果你的技术背景不涉及微软生态,Spring AI 在大多数场景下都是更好的选择——生态更成熟、文档更完整、和 Spring Boot 的集成更自然。
如果你的项目有微软背景,或者需要 SK 特有的 Prompt Function 管理能力,它值得学,而且学了你会发现它的某些设计思路确实值得借鉴。
技术选型没有绝对的好坏,只有合不合适。上面的判断标准足够让你决定要不要花时间在 Semantic Kernel 上,不需要每个框架都精通,选一两个深入研究就够了。
