检索增强的大模型工具调用:语义驱动的精准API选择技术
🔥🔥🔥Retrieval-Augmented Tool Selector 工具已开源!!!
求 Star ⭐️⭐️⭐️ :https://github.com/xiaoyesoso/retrieval-tool-selector
在大型语言模型(LLM)应用中,工具调用能力已成为连接AI与真实世界的桥梁。然而,传统方法存在工具选择不准确、参数匹配错误等问题。本文将深入探讨检索增强工具选择器(Retrieval-Augmented Tool Selector) 如何通过语义嵌入技术解决这些挑战。
引言:大模型工具调用的挑战
当前LLM工具调用面临三大核心问题:
-
幻觉问题:模型可能调用不存在的工具
-
参数歧义:对枚举型参数理解不准确
-
上下文缺失:无法有效利用历史交互信息
1. 检索增强工具选择器架构
1.1 系统整体架构
1.2 核心组件交互
2. 核心实现解析
2.1 语义嵌入引擎
class RetrievalAugmentedToolSelector:def __init__(self, tools, api_key, base_url, embedding_model="text-embedding-ada-002"):# 初始化OpenAI客户端self.client = openai.Client(api_key=api_key, base_url=base_url)# 存储工具定义和嵌入模型self.embedding_model = embedding_modelself.tools = tools# 预计算工具嵌入向量self.tool_embeddings = []self.tool_names = []self.tool_definitions = []for tool in tools:# 构建工具语义文本:名称+描述tool_name = tool["function"]["name"]tool_description = tool["function"]["description"]tool_text = f"{tool_name}: {tool_description}"# 计算嵌入向量embedding = self._get_embedding(tool_text)self.tool_embeddings.append(embedding)self.tool_names.append(tool_name)# 存储工具定义副本self.tool_definitions.append({"type": "function","function": {"name": tool_name,"description": tool_description,"parameters": tool["function"]["parameters"]
})# 转换为NumPy数组便于计算self.tool_embeddings = np.array(self.tool_embeddings)# 预计算枚举值嵌入self.enum_embeddings_cache = {}all_enum_values = set()# 收集所有枚举值for tool in tools:parameters = tool["function"]["parameters"]if "properties" in parameters:for prop in parameters["properties"].values():if "enum" in prop:for value in prop["enum"]:str_value = str(value).strip()all_enum_values.add(str_value)# 批量计算枚举值嵌入if all_enum_values:enum_values_list = list(all_enum_values)embeddings = self._get_embeddings(enum_values_list)# 创建枚举值到嵌入的映射for value, embedding in zip(enum_values_list, embeddings):self.enum_embeddings_cache[value] = embedding
2.2 工具选择算法
def select_tools(self, query, tool_threshold=0.7, tool_top_k=1, enum_threshold=0.6, enum_top_k=3):"""基于语义相似度选择最相关的工具和参数参数:query: 用户查询文本tool_threshold: 工具相似度阈值(0-1)tool_top_k: 返回的最大工具数量enum_threshold: 枚举值相似度阈值enum_top_k: 每个参数保留的最大枚举值数"""# 计算查询的嵌入向量query_embedding = self._get_embedding(query)# 计算工具相似度similarities = cosine_similarity([query_embedding], self.tool_embeddings)[0]# 按相似度排序工具tool_scores = list(enumerate(similarities))tool_scores.sort(key=lambda x: x[1], reverse=True)selected_tools = []for idx, score in tool_scores:# 应用阈值和top_k过滤if score >= tool_threshold and len(selected_tools) < tool_top_k:# 深拷贝工具定义tool_copy = json.loads(json.dumps(self.tool_definitions[idx]))# 过滤枚举参数parameters = tool_copy["function"]["parameters"]if "properties" in parameters:for prop_name, prop in parameters["properties"].items():if "enum" in prop:# 转换枚举值为字符串enum_values = [str(v).strip() for v in prop["enum"]]# 应用语义过滤prop["enum"] = self._filter_enum_values(query_embedding,enum_values,threshold=enum_threshold,top_k=enum_top_k)selected_tools.append(tool_copy)return selected_tools
2.3 枚举值过滤算法
def _filter_enum_values(self, query_embedding, enum_values, threshold, top_k):"""基于语义相似度过滤枚举值参数:query_embedding: 查询的嵌入向量enum_values: 枚举值列表threshold: 相似度阈值top_k: 保留的最大值数量"""if not enum_values:return enum_values# 获取预计算的枚举值嵌入enum_embeddings = [self.enum_embeddings_cache[value] for value in enum_values]enum_embeddings = np.array(enum_embeddings)# 计算相似度similarities = cosine_similarity([query_embedding], enum_embeddings)[0]# 创建(索引, 相似度, 值)元组enum_scores = [(i, sim, value) for i, (sim, value) in enumerate(zip(similarities, enum_values))]# 按相似度降序排序enum_scores.sort(key=lambda x: x[1], reverse=True)# 应用阈值过滤filtered_enum = []for i, sim, value in enum_scores:if sim >= threshold and len(filtered_enum) < top_k:filtered_enum.append(value)return filtered_enum
3. 语义匹配过程详解
3.1 工具选择原理
3.2 枚举值过滤原理
3.3 参数调优指南
参数 | 默认值 | 适用场景 | 调整建议 |
---|---|---|---|
tool_threshold | 0.7 | 工具匹配 | 工具数量多时提高,工具少时降低 |
tool_top_k | 1 | 多工具场景 | 根据实际工具数量调整 |
enum_threshold | 0.6 | 参数过滤 | 枚举值语义明确时提高 |
enum_top_k | 3 | 多值参数 | 根据参数复杂度调整 |
4. API服务集成实现
4.1 Flask API架构
@app.route('/v1/chat/completions', methods=['POST'])
def chat_completion():"""OpenAI兼容的聊天补全端点,带语义工具选择请求格式: https://platform.openai.com/docs/api-reference/chat/create响应格式: https://platform.openai.com/docs/api-reference/chat/object"""try:# 获取并验证请求负载payload = request.get_json()if not payload or "messages" not in payload:return jsonify({"error": {"message": "Invalid request: missing 'messages' parameter","type": "invalid_request_error"
}), 400# 增强请求:添加工具选择enhanced_payload = enhance_request(payload)# 调用OpenAI APIresponse = openai_client.chat.completions.create(enhanced_payload)# 返回OpenAI兼容响应return jsonify(response.to_dict())except Exception as e:return jsonify({"error": {"message": f"Processing error: {str(e)}","type": "server_error"
}), 500
4.2 请求增强过程
def enhance_request(payload: Dict[str, Any]) -> Dict[str, Any]:"""通过工具选择增强OpenAI请求负载保留所有原始参数"""# 创建负载副本payload = payload.copy()# 获取最新的用户消息user_query = process_message(payload.get("messages", []))if not user_query:return payload# 基于用户查询选择工具selected_tools = tool_selector.select_tools(user_query,tool_threshold=Config.TOOL_THRESHOLD,tool_top_k=Config.TOOL_TOP_K,enum_threshold=Config.ENUM_THRESHOLD,enum_top_k=Config.ENUM_TOP_K)# 添加选择的工具到请求负载payload["tools"] = selected_tools# 设置工具选择策略if "tool_choice" not in payload:payload["tool_choice"] = "auto"return payload
5. 部署与实践指南
5.1 部署架构
5.2 Docker部署示例
# 使用Python 3.10精简镜像
FROM python:3.10-slim# 设置工作目录
WORKDIR /app# 复制依赖文件
COPY requirements.txt .# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt# 复制应用代码
COPY . .# 设置环境变量
ENV OPENAI_API_KEY=your_api_key
ENV PORT=5000# 暴露端口
EXPOSE 5000# 启动命令
CMD ["python", "app.py"]