1.概述
在大模型应用中,工具调用常采用预定义的静态注册方式,导致每次请求都需向模型传递完整的工具描述,造成大量冗余Token消耗。尤其当工具集庞大时,这种开销显著增加推理成本并影响响应速度。此外,多数请求仅涉及少数相关工具,全局暴露所有工具信息效率低下。因此,亟需一种动态选择机制,根据用户输入语义实时匹配最相关的工具,仅将必要工具注入上下文。通过引入向量数据库对用户意图与工具功能进行语义嵌入匹配,可实现精准、高效的工具动态构建。这种方法不仅大幅减少输入Token使用,还能提升系统响应速度与可扩展性,是优化大模型应用性能的关键路径。
本文就使用向量数据库实现动态选择工具,下面是实现的过程。
实现流程
- 启动时将工具的元数据信息向量化到数据库
- 在查询的时候,根据用户的查询查询向量库构建工具列表
2.实现过程
2.1 准备工具类
@ToolClass
@Service
public class ToolDemo {
@Tool(description = "查询某个地区的人数")
public static String getCountByArea(String area) {
return area +"人数为:" +RandomNumberGenerator.generateRandomNumber();
}
@Tool(description = "这是一个帮人预测运势的功能,需要提供姓名 及 人的出生年月日,使用格式为 年-月-日 ")
public static String suanming(String name, String birthday) {
return name +"出生年 :" + birthday+ " 运势为:" + FortuneTeller.getRandomFortune();
}
@Tool(description = "查询某个地区的天气")
public static String getTianqiByArea(@ToolParam(description = "地区", required = true) String area) {
return area +"天气为:" +FortuneTeller.getRandomWeather();
}
}
在工具类添加 @ToolClass
,方便扫描。
2.2 启动的时候将工具类的元数据进行向量化存储
- 启动时清除工具向量
- 重新将工具的元数据存入向量数据库中
@PostConstruct
public void init() throws JsonProcessingException {
vectorStore.delete(new Filter.Expression(Filter.ExpressionType.EQ, new Filter.Key("type"), new Filter.Value("class")));
Set<Class<?>> toolClasses = scan(TOOL_CLASS_PACKAGE);
int id=1000000;
List<Document> docs = new ArrayList<>();
for (Class<?> toolClass : toolClasses) {
ToolClass toolClassAnnotation = toolClass.getAnnotation(ToolClass.class);
Method[] methods = toolClass.getDeclaredMethods();
for (Method method : methods) {
if (!method.isAnnotationPresent(Tool.class)) {
continue;
}
Tool tool = method.getAnnotation(Tool.class);
ObjectNode inputSchemaJson = InputSchemaGenerator.generateInputSchema(method);
String inputSchema = mapper.writeValueAsString(inputSchemaJson);
Map<String, Object> metadata = new HashMap<>();
metadata.put("type", "class");
metadata.put("class", toolClass.getName());
metadata.put("method", method.getName());
metadata.put("inputSchema", inputSchema);
docs.add(new Document(id +"", tool.description(), metadata));
id++;
}
//将工具向量化。
vectorStore.add(docs);
}
}
2.3 在和大模型对话的时候选择工具
public String retrieveAndGenerateDemo(String query, String sessionId) throws Exception{
List<ToolCallback> toolCallbacks = getToolBack(query);
// 2. 使用Advisor进行RAG查询
return chatClient.prompt()
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, sessionId))
.user(u -> u.text(query))
.toolCallbacks(toolCallbacks)
.call()
.content();
}
我们在和大模型对话的时候,构造出可用的工具类,这样我们就可以精准的找到工具,减少大模型token的开销 和提升性能。