函数调用:智能体的核心能力

函数调用(Function Calling)是LLM从"聊天机器人"进化为"智能体"的关键能力。Hermes 4在这一维度上做了深度优化,将函数调用的准确率从78%提升到了94%以上。本文剖析其背后的技术细节。

函数调用的三个层次

层次一:格式约束(Format-Level)

最基础的层次——确保模型输出符合可解析的函数调用格式:

// 期望格式
{
  "tool": "search_web",
  "parameters": {
    "query": "2026年AI最新进展",
    "num_results": 5
  }
}

早期模型依赖严格的格式提示词和后处理来保证格式正确性:

# 传统格式约束方法
FORMAT_PROMPT = """
你必须以严格的JSON格式回复,不要添加任何其他文本。
格式示例:
{"tool": "<函数名>", "parameters": {<参数键值对>}}

可用函数:
- search_web(query: str, num_results: int): 搜索网页
- send_email(to: str, subject: str, body: str): 发送邮件
"""

def parse_tool_call(response):
    """脆弱的JSON解析,需要大量容错处理"""
    try:
        # 尝试从回复中提取JSON
        json_str = extract_json(response)
        call = json.loads(json_str)
        return validate_call(call)
    except:
        # 格式错误时的降级处理
        return fallback_parse(response)

这种方法的问题在于:模型并不"理解"函数的用途,只是在模仿格式。

层次二:语义理解(Semantic-Level)

Hermes 4的核心突破在于让模型真正理解函数的语义——什么情况下该调用哪个函数、参数应该如何填充:

# Hermes 4 的语义级函数调用
class HermesFunctionCaller:
    def __init__(self, model, tool_registry):
        self.model = model
        self.tools = tool_registry
        
    async def call(self, user_request, context=None):
        # 1. 语义路由:理解用户意图,匹配最合适的函数
        intent = await self.model.understand_intent(user_request)
        candidate_tools = self.tools.match(intent)
        
        # 2. 参数推理:从对话中推理参数值
        for tool in candidate_tools:
            args = await self.model.infer_arguments(
                tool_schema=tool.schema,
                user_request=user_request,
                context=context
            )
            
            # 3. 完整性验证:检查必填参数
            missing = tool.check_required(args)
            if missing:
                # 主动追问缺失信息
                return {"status": "need_info", "missing": missing}
            
            # 4. 类型验证:确保参数类型正确
            if tool.validate_types(args):
                return {"status": "ready", "tool": tool.name, "args": args}
        
        return {"status": "no_match"}

层次三:链式编排(Orchestration-Level)

最复杂的层次——根据用户目标自动编排多步函数调用:

# 用户请求:"帮我查一下明天北京的天气,然后发邮件告诉张三"
# 需要链式调用:get_weather → compose_email → send_email

class HermesOrchestrator:
    async def plan_and_execute(self, user_goal, available_tools):
        # 1. 任务分解
        steps = await self.model.plan(
            goal=user_goal,
            tools=available_tools
        )
        # steps = [
        #   {"action": "get_weather", "args": {"city": "北京", "date": "明天"}},
        #   {"action": "compose_email", "depends_on": 0, "template": "weather_report"},
        #   {"action": "send_email", "depends_on": 1, "to": "张三"}
        # ]
        
        # 2. 逐步执行
        results = {}
        for i, step in enumerate(steps):
            # 注入前序结果
            if "depends_on" in step:
                step = self.inject_dependency(step, results[step["depends_on"]])
            
            # 执行函数
            result = await self.execute(step)
            results[i] = result
            
            # 3. 异常处理:如果某步失败,尝试替代方案
            if not result.success:
                alternative = await self.model.find_alternative(step, available_tools)
                if alternative:
                    results[i] = await self.execute(alternative)
        
        return results

Hermes 4的优化细节

1. 工具描述的结构化编码

Hermes 4不依赖自然语言描述工具,而是使用结构化编码:

# 传统方式:自然语言描述
tool_description = """
Search the web for information.
Args:
  query (str): The search query
  num_results (int): Number of results to return, default 5
"""

# Hermes 4:结构化语义编码
tool_schema = {
    "name": "search_web",
    "semantic_id": "information_retrieval.web_search",
    "description": {
        "purpose": "retrieve_current_information",
        "when_to_use": [
            "user_asks_about_recent_events",
            "model_knowledge_may_be_outdated",
            "user_requests_specific_facts"
        ],
        "when_not_to_use": [
            "user_asks_for_opinion",
            "information_is_in_provided_context"
        ]
    },
    "parameters": {
        "query": {
            "type": "string",
            "semantic_role": "search_topic",
            "extraction_hint": "rephrase user question as search query"
        },
        "num_results": {
            "type": "integer",
            "default": 5,
            "semantic_role": "result_count",
            "extraction_hint": "if user specifies number, use it; otherwise default"
        }
    }
}

2. 函数选择矩阵

Hermes 4在训练中构建了函数选择的决策矩阵,显著降低了误调用率:

用户意图 正确函数 常见误调用 误调用原因
“帮我查天气” get_weather search_web 语义重叠
“发邮件给张三” send_email send_message 通道混淆
“把这个文件翻译成英文” translate_text summarize_text 操作混淆
“设置每天9点提醒” create_reminder update_schedule 时序混淆

通过在训练数据中大量包含这些"易混淆"场景,Hermes 4将误调用率从12%降至3.5%。

3. 参数消歧机制

# 参数消歧示例
user_request = "帮我订一张明天去上海的机票"
# "明天"是日期参数,但今天是几号?需要从上下文推断
# "上海"是目的地,但出发地是哪里?需要追问或从用户历史推断

class ArgumentDisambiguator:
    async def disambiguate(self, tool, raw_args, context):
        disambiguated = {}
        
        for param_name, param_value in raw_args.items():
            if self.is_ambiguous(param_value):
                # 策略1:从上下文推断
                inferred = self.infer_from_context(param_value, context)
                
                if inferred:
                    disambiguated[param_name] = inferred
                elif tool.parameters[param_name].required:
                    # 策略2:追问用户
                    return {"status": "ambiguous", 
                            "param": param_name,
                            "hint": tool.parameters[param_name].extraction_hint}
                else:
                    # 策略3:使用默认值
                    disambiguated[param_name] = tool.parameters[param_name].default
            else:
                disambiguated[param_name] = param_value
        
        return {"status": "ok", "args": disambiguated}

4. 错误恢复与重试

Hermes 4在函数调用失败时具备智能恢复能力:

class ErrorRecovery:
    async def handle_failure(self, tool_call, error):
        error_type = self.classify_error(error)
        
        strategies = {
            "timeout": self.retry_with_backoff,
            "invalid_param": self.fix_and_retry,
            "permission_denied": self.request_permission,
            "not_found": self.find_alternative_tool,
            "rate_limit": self.queue_and_wait,
        }
        
        strategy = strategies.get(error_type, self.ask_user)
        return await strategy(tool_call, error)
    
    async def fix_and_retry(self, tool_call, error):
        """根据错误信息自动修复参数"""
        fix_prompt = f"""
        函数 {tool_call.tool} 调用失败。
        错误信息:{error.message}
        当前参数:{tool_call.args}
        
        请分析错误原因并修正参数。
        """
        fixed_args = await self.model.complete(fix_prompt)
        return await self.execute(tool_call.tool, fixed_args)

性能基准

函数调用准确率对比

任务复杂度 Hermes 4 Llama 4 Instruct Qwen 3 GPT-5
单函数单参数 98.1% 94.2% 95.0% 98.8%
单函数多参数 95.7% 86.3% 89.1% 96.5%
函数选择(易混淆) 93.2% 78.5% 82.1% 95.3%
并行函数调用 91.5% 72.3% 76.8% 94.2%
链式调用(3步) 87.3% 65.8% 70.2% 91.5%
链式调用(5步+) 78.6% 48.1% 55.3% 84.7%
错误恢复 82.1% 54.2% 61.5% 88.6%

实践建议

针对Hermes 4的函数定义最佳实践

# ✅ 好的函数定义
{
    "name": "search_products",
    "description": {
        "purpose": "在商品数据库中搜索商品",
        "when_to_use": "用户想要查找、比较或购买商品时",
        "when_not_to_use": "用户只是询问购物建议而无具体商品需求时"
    },
    "parameters": {
        "query": {
            "type": "string",
            "description": "搜索关键词,应提取用户提到的商品名称或类型",
            "required": true
        },
        "max_price": {
            "type": "number",
            "description": "最高价格限制,用户提到预算时填入",
            "required": false,
            "default": null
        },
        "category": {
            "type": "string",
            "enum": ["electronics", "clothing", "food", "books", "other"],
            "description": "商品类别,根据用户描述判断",
            "required": false
        }
    }
}

# ❌ 不好的函数定义(过于简略)
{
    "name": "search",
    "description": "Search products",
    "parameters": {
        "q": {"type": "string"},
        "price": {"type": "number"},
        "cat": {"type": "string"}
    }
}

结语

函数调用是智能体从"能说话"到"能做事"的桥梁。Hermes 4的优化思路——从格式约束到语义理解再到智能编排——为开源智能体生态提供了一条清晰的发展路径。当模型不仅能正确填写参数,还能理解何时调用、如何恢复、怎样编排时,真正实用的AI智能体才算成型。