Spring AI 函数调用(Function Call)系统设计方案
一、系统概述与设计目标
1.1 核心目标
从零构建一个灵活、安全、高效的函数调用系统,使大语言模型能够在对话中调用应用程序中的方法,同时保持良好的开发体验和企业级特性。
1.2 主要功能需求
- 支持通过注解将普通Java方法标记为可被AI调用的函数
- 自动生成符合LLM要求的函数描述和参数定义
- 安全地解析和执行模型的函数调用请求
- 处理并返回执行结果给模型
- 提供扩展点以支持不同LLM提供商的特定实现
1.3 设计原则
- 开发便捷性:使用声明式注解,减少开发者的工作量
- 安全可控:严格的调用权限和参数验证
- 高度可扩展:模块化设计,易于扩展新功能
- 与Spring生态集成:利用Spring的依赖注入、AOP等优势
二、系统架构设计
2.1 整体架构图
┌─────────────────────────────────────┐
│ 应用层 │
│ ┌─────────────┐ ┌──────────────┐ │
│ │用户定义的工具│ │ 业务服务 │ │
│ └─────────────┘ └──────────────┘ │
└───────────────────────┬─────────────┘│
┌───────────────────────▼─────────────┐
│ Spring AI 函数调用系统 │
│ ┌─────────────┐ ┌──────────────┐ │
│ │工具注册中心 │ │ 函数调用引擎 │ │
│ └─────────────┘ └──────────────┘ │
│ ┌─────────────┐ ┌──────────────┐ │
│ │参数转换器 │ │ 结果处理器 │ │
│ └─────────────┘ └──────────────┘ │
└───────────────────────┬─────────────┘│
┌───────────────────────▼─────────────┐
│ 模型集成层 │
│ ┌─────────────┐ ┌──────────────┐ │
│ │OpenAI适配器 │ │其他模型适配器│ │
│ └─────────────┘ └──────────────┘ │
└───────────────────────┬─────────────┘│
┌───────────────────────▼─────────────┐
│ 外部LLM接口 │
│ ┌─────────────┐ ┌──────────────┐ │
│ │OpenAI API │ │其他模型API │ │
│ └─────────────┘ └──────────────┘ │
└─────────────────────────────────────┘
2.2 核心组件
- 工具注册中心(Tool Registry):管理所有可用工具的元数据和实例
- 函数调用引擎(Function Call Engine):处理模型函数调用请求,执行目标方法
- 参数转换器(Parameter Converter):转换JSON参数为Java对象
- 结果处理器(Result Handler):处理方法执行结果,转换为标准格式
- 模型适配器(Model Adapter):适配不同LLM提供商的特定API和格式要求
三、详细设计与核心代码实现
3.1 注解定义
package org.springframework.ai.function;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 标记一个方法为AI可调用的工具函数*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Tool {/*** 工具名称,如果不提供则使用方法名*/String name() default "";/*** 工具描述,将发送给LLM帮助其理解工具用途*/String description() default "";/*** 是否直接返回结果而不传递给模型*/boolean returnDirect() default false;
}/*** 标记方法参数,提供参数描述和类型信息*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Param {/*** 参数名称*/String name() default "";/*** 参数描述*/String description() default "";/*** 是否必需*/boolean required() default true;
}
3.2 工具描述模型
package org.springframework.ai.function.model;import java.util.List;/*** 工具描述,会被转换为JSON Schema发送给LLM*/
public class ToolDescription {private String name;private String description;private List<ParameterDescription> parameters;private boolean returnDirect;// getters, setters, constructors/*** 转换为OpenAI格式的函数定义*/public Map<String, Object> toOpenAiFunctionDefinition() {Map<String, Object> function = new HashMap<>();function.put("name", this.name);function.put("description", this.description);Map<String, Object> parametersSchema = new HashMap<>();parametersSchema.put("type", "object");Map<String, Object> properties = new HashMap<>();List<String> required = new ArrayList<>();for (ParameterDescription param : parameters) {Map<String, Object> property = new HashMap<>();property.put("type", param.getType());property.put("description", param.getDescription());properties.put(param.getName(), property);if (param.isRequired()) {required.add(param.getName());}}parametersSchema.put("properties", properties);parametersSchema.put("required", required);function.put("parameters", parametersSchema);return function;}
}/*** 参数描述*/
public class ParameterDescription {private String name;private String description;private String type;private boolean required;// getters, setters, constructors
}
3.3 工具注册中心
package org.springframework.ai.function.registry;import org.springframework.ai.function.Tool;
import org.springframework.ai.function.model.ToolDescription;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;/*** 工具注册中心,管理所有可用工具*/
@Component
public class ToolRegistry {private final Map<String, ToolRegistration> registeredTools = new ConcurrentHashMap<>();private final ApplicationContext applicationContext;private final ToolDescriptionGenerator descriptionGenerator;@Autowiredpublic ToolRegistry(ApplicationContext applicationContext