知识模块
🤖 Agent 知识模块
九、工具模块
工具选择策略

工具选择策略

工具选择是 Agent 工具调用的核心环节。面对大量工具,如何让 LLM 准确选择正确的工具?本章介绍意图识别、路由机制、Tool RAG 等关键技术。


一、核心原理

1.1 工具选择的挑战

┌─────────────────────────────────────────────────────────────┐
│                    工具选择的挑战                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   问题 1: 工具数量爆炸                                      │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ 10 个工具 → 100% 放入上下文                          │  │
│   │ 100 个工具 → 上下文过长,选择困难                     │  │
│   │ 1000 个工具 → 不可能全部放入上下文                    │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   问题 2: 工具描述歧义                                      │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ "搜索" 工具 vs "查询" 工具                           │  │
│   │ "计算" 工具 vs "分析" 工具                           │  │
│   │ 功能重叠,描述模糊                                   │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   问题 3: 幻觉调用                                          │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ LLM 调用不存在的工具                                 │  │
│   │ 或者调用参数不匹配的工具                             │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   问题 4: 选择准确率低                                      │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ 工具选择准确率只有 70%                               │  │
│   │ 导致任务执行失败                                     │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 工具选择流程

┌─────────────────────────────────────────────────────────────┐
│                    工具选择流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   用户输入:"帮我查一下北京明天的天气"                      │
│                                                             │
│   Step 1: 意图识别                                          │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ 分析用户意图:                                       │  │
│   │ • 核心需求:获取天气信息                             │  │
│   │ • 数据类型:实时/预测数据                            │  │
│   │ • 操作类型:查询(非计算、非写入)                   │  │
│   │                                                      │  │
│   │ 结论:需要"信息获取"类工具                           │  │
│   └─────────────────────────────────────────────────────┘  │
│                          │                                  │
│                          ↓                                  │
│   Step 2: 工具检索                                          │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ 从工具库中检索候选工具:                             │  │
│   │ • search_web (相似度: 0.85)                          │  │
│   │ • weather_query (相似度: 0.92) ← 最佳匹配            │  │
│   │ • news_search (相似度: 0.45)                         │  │
│   │                                                      │  │
│   │ 候选集:[weather_query, search_web]                  │  │
│   └─────────────────────────────────────────────────────┘  │
│                          │                                  │
│                          ↓                                  │
│   Step 3: 工具排序                                          │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ 根据多个维度排序:                                   │  │
│   │ • 语义相似度:weather_query > search_web             │  │
│   │ • 功能匹配度:weather_query 更专精                   │  │
│   │ • 历史成功率:weather_query 95% vs search_web 80%    │  │
│   │                                                      │  │
│   │ 排序结果:weather_query > search_web                 │  │
│   └─────────────────────────────────────────────────────┘  │
│                          │                                  │
│                          ↓                                  │
│   Step 4: LLM 最终决策                                      │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ 将候选工具提供给 LLM:                               │  │
│   │ • 候选工具定义注入 Prompt                            │  │
│   │ • LLM 选择最合适的工具                               │  │
│   │ • 生成工具调用参数                                   │  │
│   │                                                      │  │
│   │ 决策:weather_query(city="北京", date="明天")        │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

二、意图识别

2.1 意图分类体系

┌─────────────────────────────────────────────────────────────┐
│                    意图分类体系                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Level 1: 操作类型                                         │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ • 信息获取 (search, query, fetch)                    │  │
│   │ • 数据处理 (calculate, analyze, transform)           │  │
│   │ • 文件操作 (read, write, delete)                     │  │
│   │ • 系统操作 (execute, run, configure)                 │  │
│   │ • 通信协作 (send, notify, schedule)                  │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   Level 2: 数据类型                                         │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ • 文本数据 (text, document, article)                 │  │
│   │ • 数值数据 (number, statistics, financial)           │  │
│   │ • 多媒体 (image, audio, video)                       │  │
│   │ • 结构化数据 (json, csv, database)                   │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   Level 3: 时效性                                           │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ • 实时数据 (realtime, current)                       │  │
│   │ • 历史数据 (historical, archive)                     │  │
│   │ • 预测数据 (forecast, prediction)                    │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   示例:                                                    │
│   "查北京明天的天气" → 信息获取 + 文本 + 预测              │
│   "计算投资回报率" → 数据处理 + 数值 + 历史                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.2 意图识别实现

"""
意图识别实现
支持关键词匹配、语义分类、LLM 分类
"""
 
from typing import List, Dict, Tuple
from dataclasses import dataclass
from enum import Enum
import re
 
 
class IntentCategory(Enum):
    """意图类别"""
    INFORMATION = "information"      # 信息获取
    PROCESSING = "processing"        # 数据处理
    FILE_OPERATION = "file"          # 文件操作
    SYSTEM = "system"                # 系统操作
    COMMUNICATION = "communication"  # 通信协作
    UNKNOWN = "unknown"              # 未知
 
 
@dataclass
class Intent:
    """意图识别结果"""
    category: IntentCategory
    confidence: float
    keywords: List[str]
    sub_intents: List[str]
 
 
class IntentClassifier:
    """
    意图分类器
    
    支持多种分类策略:
    1. 关键词匹配(快速)
    2. 规则匹配(中等)
    3. 语义分类(准确)
    4. LLM 分类(最准确但慢)
    """
    
    # 关键词映射
    KEYWORD_MAPPINGS = {
        IntentCategory.INFORMATION: [
            "查", "搜", "找", "获取", "查询", "搜索", "看看", "了解",
            "search", "query", "find", "get", "fetch", "lookup"
        ],
        IntentCategory.PROCESSING: [
            "计算", "分析", "处理", "转换", "统计", "计算器",
            "calculate", "analyze", "process", "compute", "transform"
        ],
        IntentCategory.FILE_OPERATION: [
            "文件", "读取", "写入", "保存", "删除", "创建", "打开",
            "file", "read", "write", "save", "delete", "create", "open"
        ],
        IntentCategory.SYSTEM: [
            "执行", "运行", "启动", "停止", "配置", "安装",
            "execute", "run", "start", "stop", "config", "install"
        ],
        IntentCategory.COMMUNICATION: [
            "发送", "通知", "邮件", "消息", "提醒", "分享",
            "send", "notify", "email", "message", "alert", "share"
        ]
    }
    
    def __init__(self, use_llm: bool = False, llm_client=None):
        self.use_llm = use_llm
        self.llm_client = llm_client
    
    def classify(self, text: str) -> Intent:
        """
        分类意图
        
        Args:
            text: 用户输入文本
            
        Returns:
            意图识别结果
        """
        # 方法 1: 关键词匹配
        keyword_result = self._keyword_classify(text)
        
        if keyword_result.confidence > 0.8:
            return keyword_result
        
        # 方法 2: 如果启用 LLM,使用 LLM 分类
        if self.use_llm and self.llm_client:
            return self._llm_classify(text)
        
        # 方法 3: 返回关键词结果
        return keyword_result
    
    def _keyword_classify(self, text: str) -> Intent:
        """关键词匹配分类"""
        text_lower = text.lower()
        scores: Dict[IntentCategory, Tuple[float, List[str]]] = {}
        
        for category, keywords in self.KEYWORD_MAPPINGS.items():
            matched = [kw for kw in keywords if kw in text_lower]
            if matched:
                # 计算置信度
                score = len(matched) / len(keywords)
                scores[category] = (score, matched)
        
        if not scores:
            return Intent(
                category=IntentCategory.UNKNOWN,
                confidence=0.0,
                keywords=[],
                sub_intents=[]
            )
        
        # 选择得分最高的
        best_category = max(scores, key=lambda x: scores[x][0])
        best_score, best_keywords = scores[best_category]
        
        return Intent(
            category=best_category,
            confidence=min(best_score * 2, 1.0),  # 归一化
            keywords=best_keywords,
            sub_intents=[]
        )
    
    def _llm_classify(self, text: str) -> Intent:
        """使用 LLM 进行意图分类"""
        prompt = f"""
分析以下用户输入的意图,返回 JSON 格式结果:
 
用户输入:{text}
 
返回格式:
{{
    "category": "information|processing|file|system|communication|unknown",
    "confidence": 0.0-1.0,
    "keywords": ["关键词1", "关键词2"],
    "sub_intents": ["子意图1", "子意图2"]
}}
"""
        response = self.llm_client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[{"role": "user", "content": prompt}],
            response_format={"type": "json_object"}
        )
        
        import json
        result = json.loads(response.choices[0].message.content)
        
        return Intent(
            category=IntentCategory(result.get("category", "unknown")),
            confidence=result.get("confidence", 0.5),
            keywords=result.get("keywords", []),
            sub_intents=result.get("sub_intents", [])
        )
 
 
# 使用示例
if __name__ == "__main__":
    classifier = IntentClassifier()
    
    test_cases = [
        "帮我查一下北京明天的天气",
        "计算一下投资回报率",
        "读取 config.json 文件",
        "发送邮件给张三"
    ]
    
    for text in test_cases:
        intent = classifier.classify(text)
        print(f"输入: {text}")
        print(f"意图: {intent.category.value}")
        print(f"置信度: {intent.confidence:.2f}")
        print(f"关键词: {intent.keywords}")
        print()

三、工具检索

3.1 Tool RAG 架构

┌─────────────────────────────────────────────────────────────┐
│                    Tool RAG 架构                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   离线阶段:工具向量化                                       │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                      │  │
│   │   工具定义                向量化模型         向量库   │  │
│   │   ┌─────────┐           ┌─────────┐       ┌───────┐│  │
│   │   │search   │           │         │       │v1    ││  │
│   │   │description│────────→│Embedding│──────→│v2    ││  │
│   │   │...      │           │ Model   │       │v3    ││  │
│   │   └─────────┘           │         │       │...   ││  │
│   │   ┌─────────┐           └─────────┘       └───────┘│  │
│   │   │calculate│                                       │  │
│   │   │...      │                                       │  │
│   │   └─────────┘                                       │  │
│   │                                                      │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   在线阶段:查询与检索                                       │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                      │  │
│   │   用户查询              向量化            相似检索    │  │
│   │   ┌─────────┐         ┌─────────┐       ┌───────┐  │  │
│   │   │"查天气" │────────→│Embedding│──────→│Top-K  │  │  │
│   │   └─────────┘         │ Model   │       │匹配   │  │  │
│   │                       └─────────┘       └───┬───┘  │  │
│   │                                           │      │  │
│   │                                           ↓      │  │
│   │                                    ┌───────────┐ │  │
│   │                                    │候选工具列表│ │  │
│   │                                    │[weather,  │ │  │
│   │                                    │ search]   │ │  │
│   │                                    └───────────┘ │  │
│   │                                                      │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.2 Tool RAG 实现

"""
Tool RAG 实现
基于语义相似度的工具检索
"""
 
from typing import List, Dict, Tuple
from dataclasses import dataclass
import numpy as np
 
 
@dataclass
class ToolDocument:
    """工具文档(用于向量化)"""
    name: str
    content: str  # 拼接后的描述内容
    metadata: Dict
 
 
class ToolRetriever:
    """
    工具检索器
    
    使用向量相似度检索相关工具
    """
    
    def __init__(
        self,
        embedding_model,  # 向量化模型
        top_k: int = 5,
        similarity_threshold: float = 0.5
    ):
        self.embedding_model = embedding_model
        self.top_k = top_k
        self.similarity_threshold = similarity_threshold
        
        self.tool_documents: List[ToolDocument] = []
        self.tool_vectors: np.ndarray = None
    
    def add_tools(self, tools: List[Dict]):
        """
        添加工具到检索库
        
        Args:
            tools: 工具定义列表
        """
        for tool in tools:
            # 构建文档内容
            content = self._build_tool_content(tool)
            
            doc = ToolDocument(
                name=tool.get("name", ""),
                content=content,
                metadata=tool
            )
            self.tool_documents.append(doc)
        
        # 批量向量化
        contents = [doc.content for doc in self.tool_documents]
        self.tool_vectors = self.embedding_model.embed_documents(contents)
    
    def _build_tool_content(self, tool: Dict) -> str:
        """构建工具的文本表示"""
        parts = []
        
        # 工具名称
        parts.append(f"工具名称: {tool.get('name', '')}")
        
        # 工具描述
        parts.append(f"功能描述: {tool.get('description', '')}")
        
        # 参数描述
        params = tool.get("parameters", {}).get("properties", {})
        for param_name, param_info in params.items():
            parts.append(f"参数 {param_name}: {param_info.get('description', '')}")
        
        # 标签
        if "tags" in tool:
            parts.append(f"标签: {', '.join(tool['tags'])}")
        
        return "\n".join(parts)
    
    def retrieve(self, query: str) -> List[Tuple[ToolDocument, float]]:
        """
        检索相关工具
        
        Args:
            query: 用户查询
            
        Returns:
            [(工具文档, 相似度分数), ...]
        """
        if self.tool_vectors is None or len(self.tool_documents) == 0:
            return []
        
        # 向量化查询
        query_vector = self.embedding_model.embed_query(query)
        
        # 计算相似度
        similarities = self._cosine_similarity(query_vector, self.tool_vectors)
        
        # 获取 Top-K
        top_indices = np.argsort(similarities)[::-1][:self.top_k]
        
        results = []
        for idx in top_indices:
            score = similarities[idx]
            if score >= self.similarity_threshold:
                results.append((self.tool_documents[idx], score))
        
        return results
    
    def _cosine_similarity(self, vec: np.ndarray, matrix: np.ndarray) -> np.ndarray:
        """计算余弦相似度"""
        vec_norm = vec / (np.linalg.norm(vec) + 1e-8)
        matrix_norm = matrix / (np.linalg.norm(matrix, axis=1, keepdims=True) + 1e-8)
        return np.dot(matrix_norm, vec_norm)
 
 
# 使用示例
class MockEmbeddingModel:
    """模拟向量化模型"""
    
    def embed_documents(self, texts: List[str]) -> np.ndarray:
        # 实际使用 OpenAI Embedding 或其他模型
        return np.random.rand(len(texts), 1536)
    
    def embed_query(self, text: str) -> np.ndarray:
        return np.random.rand(1536)
 
 
if __name__ == "__main__":
    # 创建检索器
    retriever = ToolRetriever(
        embedding_model=MockEmbeddingModel(),
        top_k=3
    )
    
    # 添加工具
    tools = [
        {
            "name": "search_web",
            "description": "搜索互联网获取信息",
            "parameters": {
                "properties": {
                    "query": {"description": "搜索关键词"}
                }
            },
            "tags": ["search", "web", "information"]
        },
        {
            "name": "get_weather",
            "description": "获取城市天气信息",
            "parameters": {
                "properties": {
                    "city": {"description": "城市名称"}
                }
            },
            "tags": ["weather", "information", "realtime"]
        },
        {
            "name": "calculate",
            "description": "执行数学计算",
            "parameters": {
                "properties": {
                    "expression": {"description": "数学表达式"}
                }
            },
            "tags": ["calculate", "math", "processing"]
        }
    ]
    
    retriever.add_tools(tools)
    
    # 检索
    results = retriever.retrieve("北京明天的天气")
    for doc, score in results:
        print(f"工具: {doc.name}, 相似度: {score:.3f}")

四、路由机制

4.1 分层路由架构

┌─────────────────────────────────────────────────────────────┐
│                    分层路由架构                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│                       ┌───────────┐                        │
│                       │  用户请求  │                        │
│                       └─────┬─────┘                        │
│                             │                               │
│                             ↓                               │
│   Level 1: 意图分类                                         │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                      │  │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐            │  │
│   │   │信息获取 │  │数据处理 │  │系统操作 │            │  │
│   │   └────┬────┘  └────┬────┘  └────┬────┘            │  │
│   │        │            │            │                  │  │
│   └────────┼────────────┼────────────┼──────────────────┘  │
│             │            │            │                     │
│             ↓            ↓            ↓                     │
│   Level 2: 工具类路由                                       │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                      │  │
│   │  信息层          处理层          系统层              │  │
│   │  ┌─────────┐    ┌─────────┐    ┌─────────┐          │  │
│   │  │搜索工具 │    │计算工具 │    │文件工具 │          │  │
│   │  │查询工具 │    │分析工具 │    │进程工具 │          │  │
│   │  │API工具  │    │转换工具 │    │网络工具 │          │  │
│   │  └────┬────┘    └────┬────┘    └────┬────┘          │  │
│   │       │              │              │                │  │
│   └───────┼──────────────┼──────────────┼────────────────┘  │
│           │              │              │                   │
│           ↓              ↓              ↓                   │
│   Level 3: 具体工具选择                                     │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                      │  │
│   │   在确定的工具类中,使用语义相似度选择具体工具       │  │
│   │                                                      │  │
│   │   示例:信息层 → "天气查询" → get_weather            │  │
│   │                                                      │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.2 路由器实现

"""
分层路由器实现
"""
 
from typing import List, Dict, Optional
from dataclasses import dataclass
 
 
@dataclass
class RoutingResult:
    """路由结果"""
    tool_name: str
    confidence: float
    layer_path: List[str]  # 经过的层级路径
 
 
class HierarchicalToolRouter:
    """
    分层工具路由器
    
    三层路由:
    1. 意图分类层
    2. 工具类路由层
    3. 具体工具选择层
    """
    
    def __init__(
        self,
        intent_classifier: IntentClassifier,
        tool_retriever: ToolRetriever,
        tool_registry: Dict[str, List[Dict]]  # 按类别组织的工具
    ):
        self.intent_classifier = intent_classifier
        self.tool_retriever = tool_retriever
        self.tool_registry = tool_registry
    
    def route(self, query: str) -> Optional[RoutingResult]:
        """
        路由到具体工具
        
        Args:
            query: 用户查询
            
        Returns:
            路由结果
        """
        # Level 1: 意图分类
        intent = self.intent_classifier.classify(query)
        
        if intent.category == IntentCategory.UNKNOWN:
            return None
        
        layer_path = [f"Intent: {intent.category.value}"]
        
        # Level 2: 获取该类别的工具
        category_tools = self.tool_registry.get(intent.category.value, [])
        
        if not category_tools:
            return None
        
        # Level 3: 在该类别中使用语义检索
        # 临时更新检索器
        self.tool_retriever.tool_documents = []
        self.tool_retriever.add_tools(category_tools)
        
        results = self.tool_retriever.retrieve(query)
        
        if not results:
            return None
        
        best_tool, best_score = results[0]
        layer_path.append(f"Tool: {best_tool.name}")
        
        return RoutingResult(
            tool_name=best_tool.name,
            confidence=best_score * intent.confidence,
            layer_path=layer_path
        )

五、工具选择优化

5.1 准确率优化策略

┌─────────────────────────────────────────────────────────────┐
│                    工具选择优化策略                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 工具描述优化                                            │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 问题:描述模糊,模型难以区分                          │   │
│  │                                                      │   │
│  │ 优化:                                                │   │
│  │ • 添加更多使用示例                                   │   │
│  │ • 说明适用场景和不适用场景                           │   │
│  │ • 添加反例(何时不应该使用)                         │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│  2. Few-Shot 示例                                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 在 Prompt 中添加选择示例:                           │   │
│  │                                                      │   │
│  │ 示例:                                                │   │
│  │ 用户:北京天气怎么样?                                │   │
│  │ 选择:get_weather(city="北京")                       │   │
│  │                                                      │   │
│  │ 用户:Python 怎么学?                                │   │
│  │ 选择:search_web(query="Python 教程")                │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│  3. 工具互斥声明                                            │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 声明工具之间的互斥关系:                             │   │
│  │                                                      │   │
│  │ search_web: 用于搜索通用信息                        │   │
│  │ get_weather: 专门用于天气查询,优先于 search_web     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
│  4. 历史学习                                                │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 根据历史记录调整选择策略:                           │   │
│  │                                                      │   │
│  │ • 记录每次选择的正确性                               │   │
│  │ • 调整工具权重                                       │   │
│  │ • 使用 Bandit 算法平衡探索与利用                     │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.2 历史学习实现

"""
基于历史记录的工具选择优化
"""
 
from typing import Dict, List, Tuple
from dataclasses import dataclass
from collections import defaultdict
import random
 
 
@dataclass
class ToolSelectionRecord:
    """工具选择记录"""
    query: str
    selected_tool: str
    correct: bool  # 选择是否正确
    user_feedback: str = None
 
 
class ToolSelectionOptimizer:
    """
    工具选择优化器
    
    使用 UCB (Upper Confidence Bound) 算法
    平衡探索与利用
    """
    
    def __init__(self, exploration_weight: float = 1.0):
        self.exploration_weight = exploration_weight
        
        # 统计数据
        self.tool_counts: Dict[str, int] = defaultdict(int)
        self.tool_success: Dict[str, int] = defaultdict(int)
        self.query_tool_records: Dict[str, List[ToolSelectionRecord]] = defaultdict(list)
    
    def record(self, query: str, tool: str, correct: bool):
        """记录选择结果"""
        self.tool_counts[tool] += 1
        if correct:
            self.tool_success[tool] += 1
        
        record = ToolSelectionRecord(
            query=query,
            selected_tool=tool,
            correct=correct
        )
        self.query_tool_records[query].append(record)
    
    def get_adjusted_score(self, tool: str, base_score: float) -> float:
        """
        获取调整后的分数
        
        Args:
            tool: 工具名称
            base_score: 基础分数(如相似度)
            
        Returns:
            调整后的分数
        """
        if self.tool_counts[tool] == 0:
            return base_score
        
        # 成功率
        success_rate = self.tool_success[tool] / self.tool_counts[tool]
        
        # UCB 加成
        total_count = sum(self.tool_counts.values())
        ucb_bonus = self.exploration_weight * (
            2 * np.log(total_count + 1) / self.tool_counts[tool]
        ) ** 0.5
        
        # 综合分数
        return base_score * 0.5 + success_rate * 0.3 + ucb_bonus * 0.2
    
    def rank_tools(
        self,
        tools: List[Tuple[str, float]]  # [(tool_name, base_score), ...]
    ) -> List[Tuple[str, float]]:
        """
        重排序工具列表
        
        Args:
            tools: 候选工具列表
            
        Returns:
            重排序后的列表
        """
        adjusted = [
            (tool, self.get_adjusted_score(tool, score))
            for tool, score in tools
        ]
        return sorted(adjusted, key=lambda x: x[1], reverse=True)

六、面试高频问题

Q1: 工具选择准确率只有 70% 如何优化?

答案要点

  1. 优化工具描述:更清晰的描述,添加使用示例
  2. Few-Shot 学习:在 Prompt 中添加正确选择的示例
  3. Tool RAG:使用语义检索提高候选质量
  4. 分层路由:先分类再选择,减少干扰
  5. 历史学习:根据历史反馈调整选择策略

Q2: 如何设计支持 1000+ 工具的系统?

答案要点

策略说明
分层注册工具按类别分层管理
Tool RAG语义检索,只加载相关工具
意图分类先确定大类,再细化选择
工具摘要压缩工具描述,减少 Token
缓存缓存常用查询结果

Q3: 原生 Function Calling 与 Prompt 方式的优缺点?

答案要点

方面Function CallingPrompt 方式
可靠性高(结构化输出)中(可能解析失败)
灵活性中(依赖平台支持)高(完全可控)
成本可能更高可优化 Prompt
跨平台各平台不同统一方式
调试平台限制完全可调试

Q4: 什么是 Tool RAG?如何实现?

答案要点

  1. 定义:使用检索增强生成技术选择工具
  2. 离线阶段:将工具描述向量化存储
  3. 在线阶段:查询向量化,计算相似度,返回 Top-K
  4. 优势:支持大规模工具,语义匹配准确

Q5: 如何处理工具选择冲突?

答案要点

  1. 互斥声明:明确工具之间的优先级关系
  2. 置信度阈值:只有置信度足够高才调用
  3. 用户确认:不确定时让用户选择
  4. 顺序尝试:按优先级依次尝试,失败后尝试下一个

七、小结

概念一句话总结
意图识别理解用户需求类型,缩小候选范围
Tool RAG语义检索相关工具,支持大规模场景
分层路由先分类再选择,提高准确率
历史学习根据反馈调整选择策略,持续优化
优化策略描述优化 + Few-Shot + 历史学习

一句话总结:工具选择是 Agent 工具调用的核心环节,需要结合意图识别、语义检索和分层路由来提高准确率。


最后更新:2026年3月18日