在AI应用快速发展的今天,框架选择和迁移策略直接影响着项目的成功。本文基于一个真实的企业级项目,深入分析从Microsoft Semantic Kernel迁移到Spring AI的完整实践过程,为同样面临技术选型的团队提供实战参考。
在企业级AI应用开发中,技术栈的选择往往需要平衡多个因素:开发效率、维护成本、团队技能栈、生态兼容性等。我们的项目最初基于Python的Semantic Kernel构建,但随着业务复杂度增加和团队Java技术栈的优势,迁移到Spring AI成为了必然选择。
这不仅仅是一次简单的技术栈切换,更是一次架构思维的升级——从Python的简洁灵活转向Java的工程化严谨,从单一框架依赖转向Spring生态的全面拥抱。
我们的项目是一个综合性的智能应用平台,涵盖了四大核心技术场景:
项目面临的主要挑战包括:
graph TB
subgraph "Spring AI架构层"
ChatClient["ChatClient<br/>聊天客户端"]
ToolSystem["Tool System<br/>@Tool注解"]
PromptTemplate["Prompt Templates<br/>Handlebars模板"]
VectorStore["Vector Store<br/>向量存储"]
end
subgraph "迁移核心组件"
DynamicModel["DynamicModelService<br/>动态模型服务"]
Planner["PlannerService<br/>规划服务"]
TemplateManager["PromptTemplateManager<br/>模板管理器"]
ToolLoader["ToolLoader<br/>工具加载器"]
SQLGenerator["SimpleSQLBaseFunction<br/>SQL生成器"]
end
subgraph "业务场景"
PromptBased["基于Prompt模板引擎<br/>+ 函数调用"]
ConfigDynamic["配置化动态模型调用<br/>(config.json)"]
Text2SQL["Text2SQL查询<br/>(Vanna + Milvus)"]
DirectAPI["直接API调用<br/>(ESB服务)"]
end
subgraph "原Semantic Kernel概念"
SKFunction["@sk_function<br/>→ @Tool"]
SKKernel["Kernel<br/>→ ChatClient"]
SKPlugin["Plugin<br/>→ Spring Bean"]
SKPlanner["Planner<br/>→ PlannerService"]
end
ChatClient --> DynamicModel
ToolSystem --> ToolLoader
PromptTemplate --> TemplateManager
VectorStore --> SQLGenerator
DynamicModel --> PromptBased
Planner --> ConfigDynamic
TemplateManager --> Text2SQL
ToolLoader --> DirectAPI
SKFunction -.->|迁移| ToolSystem
SKKernel -.->|迁移| ChatClient
SKPlugin -.->|迁移| ToolLoader
SKPlanner -.->|迁移| Planner
动态模型服务(DynamicModelService) 这是迁移中最关键的组件之一。在Semantic Kernel中,我们依赖Kernel来管理AI服务,而在Spring AI中,我们设计了一个更加灵活的动态模型服务:
规划服务(PlannerService) 这是智能对话的核心引擎,负责解析用户意图并调度相应的工具:
在Semantic Kernel中,我们使用@sk_function
装饰器来定义可调用的函数。迁移到Spring AI后,我们设计了一个更加强大的工具系统:
graph LR
subgraph "工具系统架构"
AutoScan["自动扫描<br/>@Tool注解"]
ConfigGen["配置生成<br/>config.json"]
SpringBean["Spring Bean<br/>工具实例"]
end
subgraph "工具类型"
GeneralTools["通用工具<br/>General Tools"]
BusinessTools["业务工具<br/>Business Tools"]
SQLTools["SQL工具<br/>Text2SQL"]
APITools["API工具<br/>ESB调用"]
end
subgraph "向量存储"
Milvus["Milvus<br/>向量数据库"]
Embedding["Embedding<br/>向量化"]
RAG["RAG检索<br/>增强生成"]
end
AutoScan --> GeneralTools
ConfigGen --> BusinessTools
SpringBean --> SQLTools
SpringBean --> APITools
SQLTools --> Milvus
Milvus --> Embedding
Embedding --> RAG
自动工具发现机制 我们的ToolLoader实现了智能的工具发现机制:
@Tool
注解方法@PostConstruct
和延迟扫描避免循环依赖模板系统是连接静态配置和动态交互的桥梁。我们选择Handlebars作为模板引擎,主要考虑:
模板渲染流程包括: 1. 模板加载:从classpath或文件系统加载模板文件 2. 上下文构建:收集用户输入、可用工具列表等上下文信息 3. 动态渲染:使用Handlebars引擎生成最终的Prompt 4. 缓存管理:缓存编译后的模板,支持热重载
这是项目中最具挑战性的功能之一。我们严格按照Vanna的架构设计,实现了完整的Text2SQL流程:
核心流程: 1. 相似问题检索:从向量数据库中检索相似的问题-SQL对 2. 表结构获取:获取相关的DDL定义 3. 文档增强:添加业务相关的文档描述 4. Prompt构建:按照Vanna的格式构建SQL生成Prompt 5. SQL提取:从AI响应中提取并验证SQL语句
向量检索优化: - 多级缓存:DDL、文档、问答对分别缓存 - 相似度阈值:设置合理的相似度阈值,过滤低质量结果 - 结果排序:按照相似度和时间戳综合排序
企业级应用的一个重要特征是配置的灵活性。我们设计了多层次的配置体系:
全局配置(llm_config.json): - AI模型的基础配置 - API密钥和访问地址 - 默认参数设置
业务配置({business}/config.json): - 业务特定的模型参数 - 执行策略配置 - 自定义提示词模板
动态配置管理: - 配置热重载,无需重启应用 - 配置验证机制,防止无效配置 - 配置版本管理,支持回滚
sequenceDiagram
participant User as 用户
participant Controller as SemanticController
participant Planner as PlannerService
participant Template as PromptTemplateManager
participant Model as DynamicModelService
participant Tools as ToolLoader
participant ChatClient as Spring AI ChatClient
User->>Controller: POST /api/v1/plan_task
Controller->>Planner: planTask(request, userToken)
Planner->>Template: renderPlanTemplate(businessType, input)
Template->>Tools: getAllAvailableTools(businessType)
Tools-->>Template: List<ToolCallback>
Template-->>Planner: 渲染后的提示词
Planner->>Model: getChatClient(businessType)
Model-->>Planner: ChatClient实例
Planner->>ChatClient: prompt().system(prompt).user(input).call()
ChatClient-->>Planner: AI响应
Planner->>Planner: parseResponse(response)
alt 有工具调用计划
Planner->>Tools: executeToolPlans(plans, businessType)
Tools-->>Planner: 工具执行结果
end
Planner-->>Controller: PlanTaskResult
Controller-->>User: PlanTaskResponse
这个流程图展示了从用户请求到最终响应的完整路径。每个环节都经过精心设计,确保高性能和高可用性。
问题:Semantic Kernel的插件系统与Spring的依赖注入机制不完全兼容
解决方案: - 设计了混合式的工具加载机制 - 支持注解驱动的自动发现 - 保留配置驱动的动态加载能力 - 实现了统一的工具调用接口
问题:企业级应用需要支持大量并发请求
解决方案: - 使用Spring的异步处理能力 - 实现了智能的线程池管理 - 设计了请求排队和限流机制 - 添加了详细的性能监控
问题:Milvus的Java客户端与Python客户端API差异较大
解决方案: - 封装了统一的VectorStore接口 - 实现了连接池管理 - 添加了自动重连和错误恢复机制 - 优化了批量操作性能
我们在多个层面实现了缓存机制:
对于外部服务的调用,我们实现了智能的连接池管理:
完善的监控体系是企业级应用的必备:
随着多模态AI的发展,我们计划扩展支持: - 图像理解和生成 - 语音输入输出 - 视频分析处理
当前的规划主要基于Prompt,未来可以考虑: - 基于强化学习的动态规划 - 多智能体协作模式 - 自适应学习机制
为了降低延迟和成本,考虑: - 本地模型部署 - 边缘推理优化 - 混合云架构
这次从Semantic Kernel到Spring AI的迁移,不仅仅是技术栈的切换,更是一次架构思维的升级。我们获得了:
对于正在考虑类似迁移的团队,我的建议是:
技术选择没有绝对的对错,只有是否适合当前的业务场景和团队状况。希望我们的实践经验能为你的技术选型提供有价值的参考。
围观我的Github Idea墙, 也许,你会遇到心仪的项目