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的开销 和提升性能。

posted on 2025-09-02 11:19  自由港  阅读(20)  评论(0)    收藏  举报