一、系统概述与设计目标
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;
@Autowired
public ToolRegistry(ApplicationContext applicationContext