<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Function Calling on On My Way</title>
    <link>https://tuanzi-wow.cn/tags/function-calling/</link>
    <description>Recent content in Function Calling on On My Way</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 12 Sep 2026 00:25:38 +0800</lastBuildDate>
    <atom:link href="https://tuanzi-wow.cn/tags/function-calling/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Function Calling（工具调用）</title>
      <link>https://tuanzi-wow.cn/agent/function-calling/</link>
      <pubDate>Sun, 06 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/agent/function-calling/</guid>
      <description>Function Calling 的原理与实战：让模型通过结构化输出调用外部工具与 API。</description>
      <content:encoded><![CDATA[<p>//我说句实在话,这个菜鸟教程写的好简单也挺烂的,不过很容易看懂吧,还真是菜鸟教程,而且代码又臭又长</p>
<h1 id="function-calling工具调用">Function Calling(工具调用)</h1>
<p>是LLM能够调用外部工具的核心机制,允许模型决定什么时候调用工具,调用什么工具,以及传递什么参数</p>
<h2 id="function-calling的工作原理">Function Calling的工作原理:</h2>
<p>其基本流程如下:</p>
<p><img alt="img" loading="lazy" src="https://www.runoob.com/wp-content/uploads/2026/02/runoob-funcall-runoob-scaled.png"></p>
<p>核心概念:
<strong>工具定义</strong>:描述一个工具的功能,参数和返回值
<strong>工具选择</strong>:LLM根据用户问题选择合适的工具
<strong>参数提取</strong>:LLM从问题中提取工具所需要的参数
<strong>结果处理</strong>:将工具执行结果整合到最终回答中</p>
<h3 id="实例说明">实例说明:</h3>
<ol>
<li>LLM 识别出需要调用天气查询工具</li>
<li>从问题中提取参数：<code>city=&quot;北京&quot;</code>, <code>date=&quot;今天&quot;</code></li>
<li>调用天气 API 获取数据</li>
<li>将天气数据整合成友好的回答返回给用户</li>
</ol>
<h2 id="工具定义和描述编写">工具定义和描述编写</h2>
<p>好的工具定义应该描述:
what:工具的功能 when:什么时候调用它 how:需要的参数;参数的格式;返回值</p>
<h3 id="工具定义的结构">工具定义的结构:</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="c1"># 工具定义示例结构</span>
</span></span><span class="line"><span class="cl"><span class="n">weather_tool</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;get_weather&#34;</span><span class="p">,</span>  <span class="c1"># 工具名称</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;获取指定城市的天气信息&#34;</span><span class="p">,</span>  <span class="c1"># 工具描述</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;parameters&#34;</span><span class="p">:</span> <span class="p">{</span>  <span class="c1"># 参数定义</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;object&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;city&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;城市名称，如&#39;北京&#39;、&#39;上海&#39;&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;日期，格式&#39;YYYY-MM-DD&#39;，或&#39;今天&#39;、&#39;明天&#39;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;enum&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;今天&#34;</span><span class="p">,</span> <span class="s2">&#34;明天&#34;</span><span class="p">,</span> <span class="s2">&#34;后天&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;required&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;city&#34;</span><span class="p">]</span>  <span class="c1"># 必填参数</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="编写优质的工具描述">编写优质的工具描述:</h3>
<p>1.描述要具体,例如:</p>
<ul>
<li><strong>不好的描述</strong>：查询天气</li>
<li><strong>好的描述</strong>：获取指定城市在特定日期的天气信息，包括温度、湿度、风速和天气状况（晴、雨、多云等）</li>
</ul>
<p>2.参数描述要具体:<strong>不好的参数描述</strong>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&#34;city&#34;: {&#34;type&#34;: &#34;string&#34;}
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>好的参数描述：</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&#34;city&#34;: {
</span></span><span class="line"><span class="cl">    &#34;type&#34;: &#34;string&#34;,
</span></span><span class="line"><span class="cl">    &#34;description&#34;: &#34;完整的城市名称，如&#39;北京市&#39;、&#39;上海市&#39;。不要使用简称或拼音。&#34;
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></td></tr></table>
</div>
</div><p>3.使用枚举项限制选项
对于有限的选择,是一种很好的约束手段:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="s2">&#34;unit&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;温度单位&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;enum&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;celsius&#34;</span><span class="p">,</span> <span class="s2">&#34;fahrenheit&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;default&#34;</span><span class="p">:</span> <span class="s2">&#34;celsius&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>4.提供示例值
在描述中提供示例,帮助LLM理解:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&#34;date&#34;: {
</span></span><span class="line"><span class="cl">    &#34;type&#34;: &#34;string&#34;,
</span></span><span class="line"><span class="cl">    &#34;description&#34;: &#34;日期，格式应为&#39;YYYY-MM-DD&#39;，例如&#39;2024-06-15&#39;&#34;
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="示例">示例:</h3>
<p>文件读取工具的定义</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">file_tool</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;read_file&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;读取指定文件的内容&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;parameters&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;object&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;file_path&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;文件的完整路径，如&#39;/home/user/document.txt&#39;&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;encoding&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;文件编码，默认为&#39;utf-8&#39;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;default&#34;</span><span class="p">:</span> <span class="s2">&#34;utf-8&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;required&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;file_path&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="工具定义的验证">工具定义的验证</h3>
<p>定义工具之后,应该进行验证测试:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">validate_tool_definition</span><span class="p">(</span><span class="n">tool_def</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;验证工具定义是否完整&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">required_fields</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;name&#34;</span><span class="p">,</span> <span class="s2">&#34;description&#34;</span><span class="p">,</span> <span class="s2">&#34;parameters&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">required_fields</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">tool_def</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">False</span><span class="p">,</span> <span class="n">f</span><span class="s2">&#34;缺少必要字段: {field}&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 检查参数结构</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="s2">&#34;properties&#34;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">tool_def</span><span class="p">[</span><span class="s2">&#34;parameters&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">False</span><span class="p">,</span> <span class="s2">&#34;参数定义缺少properties字段&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">True</span><span class="p">,</span> <span class="s2">&#34;工具定义完整&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 测试验证</span>
</span></span><span class="line"><span class="cl"><span class="n">is_valid</span><span class="p">,</span> <span class="n">message</span> <span class="o">=</span> <span class="n">validate_tool_definition</span><span class="p">(</span><span class="n">weather_tool</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;验证结果: {is_valid}, 消息: {message}&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="参数提取的验证">参数提取的验证</h2>
<p>LLM从问题中提取出参数之后,会对这些参数进行验证和处理,保证工具能正确执行</p>
<h3 id="参数提取过程">参数提取过程:</h3>
<p>分析输出并提取需要的参数:</p>
<h3 id="参数提取的挑战">参数提取的挑战:</h3>
<p>信息缺失:没有提供所有的必须信息
格式不符:提供的格式与定义不符
歧义解析:同一信息可能由歧义
上下文依赖:参数需要结合历史对话理解</p>
<h3 id="参数验证方法">参数验证方法:</h3>
<p>1.类型验证:验证参数类型符合要求</p>
<pre><code>def validate_parameters(params, tool_def):
    &quot;&quot;&quot;验证参数类型&quot;&quot;&quot;
    errors = []
    for param_name, param_def in tool_def[&quot;parameters&quot;]		[&quot;properties&quot;].items():
    if param_name in params:
        param_value = params[param_name]
        expected_type = param_def.get(&quot;type&quot;)

        # 类型检查
        if expected_type == &quot;string&quot; and not isinstance(param_value, str):
            errors.append(f&quot;参数'{param_name}'应为字符串类型&quot;)
        elif expected_type == &quot;integer&quot; and not isinstance(param_value, int):
            errors.append(f&quot;参数'{param_name}'应为整数类型&quot;)
        elif expected_type == &quot;number&quot; and not isinstance(param_value, (int, float)):
            errors.append(f&quot;参数'{param_name}'应为数字类型&quot;)
        elif expected_type == &quot;boolean&quot; and not isinstance(param_value, bool):
            errors.append(f&quot;参数'{param_name}'应为布尔类型&quot;)

return errors
</code></pre>
<p>2.范围验证:检查参数值是否在允许范围内:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">validate_range</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">tool_def</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;验证参数范围&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">param_name</span><span class="p">,</span> <span class="n">param_def</span> <span class="ow">in</span> <span class="n">tool_def</span><span class="p">[</span><span class="s2">&#34;parameters&#34;</span><span class="p">][</span><span class="s2">&#34;properties&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">param_name</span> <span class="ow">in</span> <span class="n">params</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">param_value</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="n">param_name</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="c1"># 检查最小值</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="s2">&#34;minimum&#34;</span> <span class="ow">in</span> <span class="n">param_def</span> <span class="ow">and</span> <span class="n">param_value</span> <span class="o">&lt;</span> <span class="n">param_def</span><span class="p">[</span><span class="s2">&#34;minimum&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">                <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;不能小于{param_def[&#39;minimum&#39;]}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="c1"># 检查最大值</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="s2">&#34;maximum&#34;</span> <span class="ow">in</span> <span class="n">param_def</span> <span class="ow">and</span> <span class="n">param_value</span> <span class="o">&gt;</span> <span class="n">param_def</span><span class="p">[</span><span class="s2">&#34;maximum&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">                <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;不能大于{param_def[&#39;maximum&#39;]}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="c1"># 检查枚举值</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="s2">&#34;enum&#34;</span> <span class="ow">in</span> <span class="n">param_def</span> <span class="ow">and</span> <span class="n">param_value</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">param_def</span><span class="p">[</span><span class="s2">&#34;enum&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">                <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;必须是{param_def[&#39;enum&#39;]}中的一个&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">errors</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>3.必填参数检验:
所有必填参数都已提供</p>
<p>完整的参数检验系统:类型,范围,必需值</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="k">class</span> <span class="n">ParameterValidator</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;参数验证器&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tool_def</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">tool_def</span> <span class="o">=</span> <span class="n">tool_def</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;执行完整的参数验证&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">all_errors</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 检查必填参数</span>
</span></span><span class="line"><span class="cl">        <span class="n">required_errors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">validate_required</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">all_errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">required_errors</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 检查参数类型</span>
</span></span><span class="line"><span class="cl">        <span class="n">type_errors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">validate_type</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">all_errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">type_errors</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 检查参数范围</span>
</span></span><span class="line"><span class="cl">        <span class="n">range_errors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">validate_range</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">all_errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">range_errors</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 检查额外参数（未定义的参数）</span>
</span></span><span class="line"><span class="cl">        <span class="n">extra_errors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">validate_extra</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">all_errors</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">extra_errors</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">len</span><span class="p">(</span><span class="n">all_errors</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">all_errors</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">validate_required</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;验证必填参数&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">        <span class="n">required_params</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tool_def</span><span class="p">[</span><span class="s2">&#34;parameters&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;required&#34;</span><span class="p">,</span> <span class="p">[])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">param_name</span> <span class="ow">in</span> <span class="n">required_params</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">param_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">params</span> <span class="ow">or</span> <span class="n">params</span><span class="p">[</span><span class="n">param_name</span><span class="p">]</span> <span class="n">is</span> <span class="n">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;缺少必填参数: {param_name}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">errors</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">validate_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;验证参数类型&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">param_name</span><span class="p">,</span> <span class="n">param_value</span> <span class="ow">in</span> <span class="n">params</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">param_name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">tool_def</span><span class="p">[</span><span class="s2">&#34;parameters&#34;</span><span class="p">][</span><span class="s2">&#34;properties&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">                <span class="n">param_def</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tool_def</span><span class="p">[</span><span class="s2">&#34;parameters&#34;</span><span class="p">][</span><span class="s2">&#34;properties&#34;</span><span class="p">][</span><span class="n">param_name</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">                <span class="n">expected_type</span> <span class="o">=</span> <span class="n">param_def</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;type&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="n">expected_type</span> <span class="o">==</span> <span class="s2">&#34;string&#34;</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">isinstance</span><span class="p">(</span><span class="n">param_value</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                    <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;应为字符串类型，实际为{type(param_value).__name__}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">elif</span> <span class="n">expected_type</span> <span class="o">==</span> <span class="s2">&#34;integer&#34;</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">isinstance</span><span class="p">(</span><span class="n">param_value</span><span class="p">,</span> <span class="ne">int</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                    <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;应为整数类型，实际为{type(param_value).__name__}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">elif</span> <span class="n">expected_type</span> <span class="o">==</span> <span class="s2">&#34;number&#34;</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">isinstance</span><span class="p">(</span><span class="n">param_value</span><span class="p">,</span> <span class="p">(</span><span class="ne">int</span><span class="p">,</span> <span class="ne">float</span><span class="p">)):</span>
</span></span><span class="line"><span class="cl">                    <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;应为数字类型，实际为{type(param_value).__name__}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">elif</span> <span class="n">expected_type</span> <span class="o">==</span> <span class="s2">&#34;boolean&#34;</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">isinstance</span><span class="p">(</span><span class="n">param_value</span><span class="p">,</span> <span class="ne">bool</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                    <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;应为布尔类型，实际为{type(param_value).__name__}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">errors</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">validate_range</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;验证参数范围&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">param_name</span><span class="p">,</span> <span class="n">param_value</span> <span class="ow">in</span> <span class="n">params</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">param_name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">tool_def</span><span class="p">[</span><span class="s2">&#34;parameters&#34;</span><span class="p">][</span><span class="s2">&#34;properties&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">                <span class="n">param_def</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tool_def</span><span class="p">[</span><span class="s2">&#34;parameters&#34;</span><span class="p">][</span><span class="s2">&#34;properties&#34;</span><span class="p">][</span><span class="n">param_name</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="c1"># 检查最小值</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="s2">&#34;minimum&#34;</span> <span class="ow">in</span> <span class="n">param_def</span> <span class="ow">and</span> <span class="n">param_value</span> <span class="o">&lt;</span> <span class="n">param_def</span><span class="p">[</span><span class="s2">&#34;minimum&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">                    <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;不能小于{param_def[&#39;minimum&#39;]}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="c1"># 检查最大值</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="s2">&#34;maximum&#34;</span> <span class="ow">in</span> <span class="n">param_def</span> <span class="ow">and</span> <span class="n">param_value</span> <span class="o">&gt;</span> <span class="n">param_def</span><span class="p">[</span><span class="s2">&#34;maximum&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">                    <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;不能大于{param_def[&#39;maximum&#39;]}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="c1"># 检查枚举值</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="s2">&#34;enum&#34;</span> <span class="ow">in</span> <span class="n">param_def</span> <span class="ow">and</span> <span class="n">param_value</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">param_def</span><span class="p">[</span><span class="s2">&#34;enum&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">                    <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;参数&#39;{param_name}&#39;必须是{param_def[&#39;enum&#39;]}中的一个&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">errors</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">validate_extra</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;检查未定义的额外参数&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">        <span class="n">defined_params</span> <span class="o">=</span> <span class="n">set</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tool_def</span><span class="p">[</span><span class="s2">&#34;parameters&#34;</span><span class="p">][</span><span class="s2">&#34;properties&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="n">provided_params</span> <span class="o">=</span> <span class="n">set</span><span class="p">(</span><span class="n">params</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">extra_params</span> <span class="o">=</span> <span class="n">provided_params</span> <span class="o">-</span> <span class="n">defined_params</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">extra_params</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;提供了未定义的参数: {&#39;, &#39;.join(extra_params)}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">errors</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 使用示例</span>
</span></span><span class="line"><span class="cl"><span class="n">validator</span> <span class="o">=</span> <span class="n">ParameterValidator</span><span class="p">(</span><span class="n">weather_tool</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">params</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;city&#34;</span><span class="p">:</span> <span class="s2">&#34;北京&#34;</span><span class="p">,</span> <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;明天&#34;</span><span class="p">,</span> <span class="s2">&#34;extra&#34;</span><span class="p">:</span> <span class="s2">&#34;不应该有的参数&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="n">is_valid</span><span class="p">,</span> <span class="n">errors</span> <span class="o">=</span> <span class="n">validator</span><span class="o">.</span><span class="n">validate</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">is_valid</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;参数验证通过&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;参数验证失败:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">error</span> <span class="ow">in</span> <span class="n">errors</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">f</span><span class="s2">&#34;  - {error}&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>参数提取和验证的完整流程</p>
<img src="https://www.runoob.com/wp-content/uploads/2026/02/runoob-funcall-runoob-2-scaled.png" alt="img" style="zoom: 15%;" />
<h3 id="参数修正的策略">参数修正的策略</h3>
<p>询问客户:直接向客户询问缺失和错误的参数
使用默认值:可以预先设定默认值
智能推断:根据上下文推断合理的参数值
格式转换:将用户提供的格式转化成工具要求的格式</p>
<h2 id="错误处理和重试机制">错误处理和重试机制</h2>
<p>工具调用可能会失败,健全的错误处理和重试机制是构建可靠的AI Agent的挂件</p>
<h3 id="常见的工具调用错误">常见的工具调用错误:</h3>
<p>网络错误:API调用超时,连接错误
参数错误:参数验证失败,格式不正确
权限错误:API密钥无效,权限不足
资源错误:服务不可达,达到调用限制
逻辑错误:工具内部逻辑错误</p>
<h3 id="错误处理策略">错误处理策略</h3>
<h4 id="1分级错误处理">1.分级错误处理:</h4>
<p>根据错误类型采取不同的处理策略</p>
<pre><code>class ErrorHandler:
    &quot;&quot;&quot;错误处理器&quot;&quot;&quot;

    def handle(self, error, context):
        &quot;&quot;&quot;处理错误&quot;&quot;&quot;
        error_type = self.classify_error(error)

        if error_type == &quot;network&quot;:
            return self.handle_network_error(error, context)
        elif error_type == &quot;parameter&quot;:
            return self.handle_parameter_error(error, context)
        elif error_type == &quot;authentication&quot;:
            return self.handle_auth_error(error, context)
        elif error_type == &quot;resource&quot;:
            return self.handle_resource_error(error, context)
        else:
            return self.handle_unknown_error(error, context)

    def classify_error(self, error):
        &quot;&quot;&quot;分类错误类型&quot;&quot;&quot;
        error_str = str(error).lower()

        if any(word in error_str for word in [&quot;timeout&quot;, &quot;connection&quot;, &quot;network&quot;]):
            return &quot;network&quot;
        elif any(word in error_str for word in [&quot;parameter&quot;, &quot;invalid&quot;, &quot;missing&quot;]):
            return &quot;parameter&quot;
        elif any(word in error_str for word in [&quot;auth&quot;, &quot;key&quot;, &quot;permission&quot;]):
            return &quot;authentication&quot;
        elif any(word in error_str for word in [&quot;limit&quot;, &quot;quota&quot;, &quot;unavailable&quot;]):
            return &quot;resource&quot;
        else:
            return &quot;unknown&quot;

    def handle_network_error(self, error, context):
        &quot;&quot;&quot;处理网络错误&quot;&quot;&quot;
        return {
            &quot;success&quot;: False,
            &quot;error&quot;: &quot;网络连接失败，请检查网络后重试&quot;,
            &quot;retryable&quot;: True,
            &quot;retry_after&quot;: 5  # 5秒后重试
        }

    def handle_parameter_error(self, error, context):
        &quot;&quot;&quot;处理参数错误&quot;&quot;&quot;
        return {
            &quot;success&quot;: False,
            &quot;error&quot;: f&quot;参数错误: {str(error)}&quot;,
            &quot;retryable&quot;: False,
            &quot;suggestion&quot;: &quot;请检查输入参数是否正确&quot;
        }

    # 其他错误处理方法类似...
</code></pre>
<h4 id="2用户友好的错误信息">2.用户友好的错误信息</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">def user_friendly_error(error):
</span></span><span class="line"><span class="cl">    &#34;&#34;&#34;生成用户友好的错误消息&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">    error_map = {
</span></span><span class="line"><span class="cl">        &#34;timeout&#34;: &#34;请求超时，请稍后重试&#34;,
</span></span><span class="line"><span class="cl">        &#34;connection_error&#34;: &#34;网络连接失败，请检查网络&#34;,
</span></span><span class="line"><span class="cl">        &#34;invalid_api_key&#34;: &#34;API 密钥无效，请检查配置&#34;,
</span></span><span class="line"><span class="cl">        &#34;rate_limit_exceeded&#34;: &#34;调用频率过高，请稍后再试&#34;,
</span></span><span class="line"><span class="cl">        &#34;invalid_parameters&#34;: &#34;输入参数不正确，请检查后重试&#34;
</span></span><span class="line"><span class="cl">    }
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    error_str = str(error).lower()
</span></span><span class="line"><span class="cl">    for key, message in error_map.items():
</span></span><span class="line"><span class="cl">        if key in error_str:
</span></span><span class="line"><span class="cl">            return message
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    return &#34;系统繁忙，请稍后重试&#34;
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="重试机制">重试机制</h3>
<h4 id="1指数退避重试">1.指数退避重试:</h4>
<p>指的是等待时间随着重试次数呈指数级增长
等待时间:指数退避+随机抖动</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import time
</span></span><span class="line"><span class="cl">import random
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">class ExponentialBackoffRetry:
</span></span><span class="line"><span class="cl">    &#34;&#34;&#34;指数退避重试&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def __init__(self, max_retries=3, base_delay=1, max_delay=30):
</span></span><span class="line"><span class="cl">        self.max_retries = max_retries
</span></span><span class="line"><span class="cl">        self.base_delay = base_delay
</span></span><span class="line"><span class="cl">        self.max_delay = max_delay
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def retry(self, func, *args, **kwargs):
</span></span><span class="line"><span class="cl">        &#34;&#34;&#34;执行带重试的函数调用&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">        last_error = None
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        for attempt in range(self.max_retries):
</span></span><span class="line"><span class="cl">            try:
</span></span><span class="line"><span class="cl">                return func(*args, **kwargs)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            except Exception as e:
</span></span><span class="line"><span class="cl">                last_error = e
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                # 检查是否可重试
</span></span><span class="line"><span class="cl">                if not self.is_retryable(e):
</span></span><span class="line"><span class="cl">                    raise
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                # 最后一次尝试，不再重试
</span></span><span class="line"><span class="cl">                if attempt == self.max_retries - 1:
</span></span><span class="line"><span class="cl">                    break
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                # 计算等待时间（指数退避 + 随机抖动）
</span></span><span class="line"><span class="cl">                delay = min(
</span></span><span class="line"><span class="cl">                    self.base_delay * (2 ** attempt) + random.uniform(0, 1),
</span></span><span class="line"><span class="cl">                    self.max_delay
</span></span><span class="line"><span class="cl">                )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                print(f&#34;第{attempt + 1}次尝试失败，{delay:.1f}秒后重试...&#34;)
</span></span><span class="line"><span class="cl">                time.sleep(delay)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        # 所有重试都失败
</span></span><span class="line"><span class="cl">        raise last_error
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def is_retryable(self, error):
</span></span><span class="line"><span class="cl">        &#34;&#34;&#34;判断错误是否可重试&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">        error_str = str(error).lower()
</span></span><span class="line"><span class="cl">        retryable_errors = [&#34;timeout&#34;, &#34;connection&#34;, &#34;busy&#34;, &#34;temporarily&#34;]
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        for retryable_error in retryable_errors:
</span></span><span class="line"><span class="cl">            if retryable_error in error_str:
</span></span><span class="line"><span class="cl">                return True
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        return False
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># 使用示例
</span></span><span class="line"><span class="cl">retry = ExponentialBackoffRetry(max_retries=3)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">def call_weather_api(city, date):
</span></span><span class="line"><span class="cl">    &#34;&#34;&#34;调用天气API（模拟可能失败）&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">    # 模拟API调用
</span></span><span class="line"><span class="cl">    if random.random() &lt; 0.3:  # 30%概率失败
</span></span><span class="line"><span class="cl">        raise ConnectionError(&#34;API连接超时&#34;)
</span></span><span class="line"><span class="cl">    return {&#34;temperature&#34;: 25, &#34;condition&#34;: &#34;晴&#34;}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">try:
</span></span><span class="line"><span class="cl">    result = retry.retry(call_weather_api, &#34;北京&#34;, &#34;今天&#34;)
</span></span><span class="line"><span class="cl">    print(f&#34;成功获取天气: {result}&#34;)
</span></span><span class="line"><span class="cl">except Exception as e:
</span></span><span class="line"><span class="cl">    print(f&#34;获取天气失败: {e}&#34;)
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="2熔断器模式">2.熔断器模式</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class CircuitBreaker:
</span></span><span class="line"><span class="cl">    &#34;&#34;&#34;熔断器&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def __init__(self, failure_threshold=5, reset_timeout=60):
</span></span><span class="line"><span class="cl">        self.failure_threshold = failure_threshold
</span></span><span class="line"><span class="cl">        self.reset_timeout = reset_timeout
</span></span><span class="line"><span class="cl">        self.failure_count = 0
</span></span><span class="line"><span class="cl">        self.last_failure_time = None
</span></span><span class="line"><span class="cl">        self.state = &#34;closed&#34;  # closed, open, half-open
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def execute(self, func, *args, **kwargs):
</span></span><span class="line"><span class="cl">        &#34;&#34;&#34;通过熔断器执行函数&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">        if self.state == &#34;open&#34;:
</span></span><span class="line"><span class="cl">            # 检查是否应该尝试恢复
</span></span><span class="line"><span class="cl">            if self.should_try_reset():
</span></span><span class="line"><span class="cl">                self.state = &#34;half-open&#34;
</span></span><span class="line"><span class="cl">            else:
</span></span><span class="line"><span class="cl">                raise Exception(&#34;熔断器开启，服务暂时不可用&#34;)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        try:
</span></span><span class="line"><span class="cl">            result = func(*args, **kwargs)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            # 成功调用，重置状态
</span></span><span class="line"><span class="cl">            if self.state == &#34;half-open&#34;:
</span></span><span class="line"><span class="cl">                self.state = &#34;closed&#34;
</span></span><span class="line"><span class="cl">                self.failure_count = 0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            return result
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        except Exception as e:
</span></span><span class="line"><span class="cl">            self.record_failure()
</span></span><span class="line"><span class="cl">            raise e
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def record_failure(self):
</span></span><span class="line"><span class="cl">        &#34;&#34;&#34;记录失败&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">        self.failure_count += 1
</span></span><span class="line"><span class="cl">        self.last_failure_time = time.time()
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        if self.failure_count &gt;= self.failure_threshold:
</span></span><span class="line"><span class="cl">            self.state = &#34;open&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def should_try_reset(self):
</span></span><span class="line"><span class="cl">        &#34;&#34;&#34;检查是否应该尝试重置&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">        if self.last_failure_time is None:
</span></span><span class="line"><span class="cl">            return True
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        elapsed = time.time() - self.last_failure_time
</span></span><span class="line"><span class="cl">        return elapsed &gt; self.reset_timeout
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># 使用示例
</span></span><span class="line"><span class="cl">breaker = CircuitBreaker(failure_threshold=3, reset_timeout=30)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">def unreliable_service():
</span></span><span class="line"><span class="cl">    &#34;&#34;&#34;模拟不可靠的服务&#34;&#34;&#34;
</span></span><span class="line"><span class="cl">    if random.random() &lt; 0.5:
</span></span><span class="line"><span class="cl">        raise Exception(&#34;服务异常&#34;)
</span></span><span class="line"><span class="cl">    return &#34;服务正常&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">for i in range(10):
</span></span><span class="line"><span class="cl">    try:
</span></span><span class="line"><span class="cl">        result = breaker.execute(unreliable_service)
</span></span><span class="line"><span class="cl">        print(f&#34;调用{i+1}: {result}&#34;)
</span></span><span class="line"><span class="cl">    except Exception as e:
</span></span><span class="line"><span class="cl">        print(f&#34;调用{i+1}: {e}&#34;)
</span></span><span class="line"><span class="cl">        time.sleep(1)
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="完整的工具框架">完整的工具框架</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="k">class</span> <span class="n">ToolExecutor</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;工具执行器&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">tools</span> <span class="o">=</span> <span class="p">{}</span>  <span class="c1"># 注册的工具</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">validator</span> <span class="o">=</span> <span class="n">ParameterValidator</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">error_handler</span> <span class="o">=</span> <span class="n">ErrorHandler</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">retry</span> <span class="o">=</span> <span class="n">ExponentialBackoffRetry</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">breaker</span> <span class="o">=</span> <span class="n">CircuitBreaker</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">register_tool</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">tool_def</span><span class="p">,</span> <span class="k">func</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;注册工具&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">tools</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;definition&#34;</span><span class="p">:</span> <span class="n">tool_def</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;function&#34;</span><span class="p">:</span> <span class="k">func</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">execute_tool</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tool_name</span><span class="p">,</span> <span class="n">params</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;执行工具&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">tool_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">tools</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;success&#34;</span><span class="p">:</span> <span class="n">False</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;error&#34;</span><span class="p">:</span> <span class="n">f</span><span class="s2">&#34;工具&#39;{tool_name}&#39;未注册&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">tool_info</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tools</span><span class="p">[</span><span class="n">tool_name</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="n">tool_def</span> <span class="o">=</span> <span class="n">tool_info</span><span class="p">[</span><span class="s2">&#34;definition&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="n">tool_func</span> <span class="o">=</span> <span class="n">tool_info</span><span class="p">[</span><span class="s2">&#34;function&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 验证参数</span>
</span></span><span class="line"><span class="cl">        <span class="n">validator</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">validator</span><span class="p">(</span><span class="n">tool_def</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">is_valid</span><span class="p">,</span> <span class="n">errors</span> <span class="o">=</span> <span class="n">validator</span><span class="o">.</span><span class="n">validate</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="ow">not</span> <span class="n">is_valid</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;success&#34;</span><span class="p">:</span> <span class="n">False</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;error&#34;</span><span class="p">:</span> <span class="s2">&#34;参数验证失败&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;details&#34;</span><span class="p">:</span> <span class="n">errors</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 通过熔断器执行（带重试）</span>
</span></span><span class="line"><span class="cl">        <span class="n">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">def</span> <span class="nf">execute_with_retry</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">breaker</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="n">lambda</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">retry</span><span class="o">.</span><span class="n">retry</span><span class="p">(</span><span class="n">tool_func</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">result</span> <span class="o">=</span> <span class="n">execute_with_retry</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;success&#34;</span><span class="p">:</span> <span class="n">True</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;result&#34;</span><span class="p">:</span> <span class="n">result</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;tool&#34;</span><span class="p">:</span> <span class="n">tool_name</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">except</span> <span class="n">Exception</span> <span class="n">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># 错误处理</span>
</span></span><span class="line"><span class="cl">            <span class="n">error_response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">error_handler</span><span class="o">.</span><span class="n">handle</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;tool&#34;</span><span class="p">:</span> <span class="n">tool_name</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;params&#34;</span><span class="p">:</span> <span class="n">params</span>
</span></span><span class="line"><span class="cl">            <span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;success&#34;</span><span class="p">:</span> <span class="n">False</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;error&#34;</span><span class="p">:</span> <span class="n">error_response</span><span class="p">[</span><span class="s2">&#34;error&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;retryable&#34;</span><span class="p">:</span> <span class="n">error_response</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;retryable&#34;</span><span class="p">,</span> <span class="n">False</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;suggestion&#34;</span><span class="p">:</span> <span class="n">error_response</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;suggestion&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">handle_user_request</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user_input</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;处理用户请求（简化版）&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 1. 让LLM选择工具和提取参数（这里简化处理）</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 实际应用中，这里会调用LLM进行工具选择和参数提取</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 模拟LLM的输出</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="s2">&#34;天气&#34;</span> <span class="ow">in</span> <span class="n">user_input</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">tool_name</span> <span class="o">=</span> <span class="s2">&#34;get_weather&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># 简单提取城市（实际应用中LLM会做得更好）</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="s2">&#34;北京&#34;</span> <span class="ow">in</span> <span class="n">user_input</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">params</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;city&#34;</span><span class="p">:</span> <span class="s2">&#34;北京&#34;</span><span class="p">,</span> <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;今天&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">elif</span> <span class="s2">&#34;上海&#34;</span> <span class="ow">in</span> <span class="n">user_input</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">params</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;city&#34;</span><span class="p">:</span> <span class="s2">&#34;上海&#34;</span><span class="p">,</span> <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;今天&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">params</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;city&#34;</span><span class="p">:</span> <span class="s2">&#34;北京&#34;</span><span class="p">,</span> <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;今天&#34;</span><span class="p">}</span>  <span class="c1"># 默认值</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="s2">&#34;抱歉，我无法处理这个请求&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 2. 执行工具</span>
</span></span><span class="line"><span class="cl">        <span class="n">result</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">execute_tool</span><span class="p">(</span><span class="n">tool_name</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># 3. 生成最终回答</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">result</span><span class="p">[</span><span class="s2">&#34;success&#34;</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">            <span class="n">weather</span> <span class="o">=</span> <span class="n">result</span><span class="p">[</span><span class="s2">&#34;result&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">f</span><span class="s2">&#34;{params[&#39;city&#39;]}今天天气：{weather[&#39;condition&#39;]}，温度{weather[&#39;temperature&#39;]}°C&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">f</span><span class="s2">&#34;获取天气信息失败：{result[&#39;error&#39;]}&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 使用示例</span>
</span></span><span class="line"><span class="cl"><span class="n">executor</span> <span class="o">=</span> <span class="n">ToolExecutor</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 注册天气工具</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">mock_weather_api</span><span class="p">(</span><span class="n">city</span><span class="p">,</span> <span class="n">date</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;模拟天气API&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># 模拟API调用延迟</span>
</span></span><span class="line"><span class="cl">    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">{</span><span class="s2">&#34;temperature&#34;</span><span class="p">:</span> <span class="mi">22</span><span class="p">,</span> <span class="s2">&#34;condition&#34;</span><span class="p">:</span> <span class="s2">&#34;多云&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">executor</span><span class="o">.</span><span class="n">register_tool</span><span class="p">(</span><span class="s2">&#34;get_weather&#34;</span><span class="p">,</span> <span class="n">weather_tool</span><span class="p">,</span> <span class="n">mock_weather_api</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 处理用户请求</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="n">handle_user_request</span><span class="p">(</span><span class="s2">&#34;北京今天天气怎么样？&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div>]]></content:encoded>
    </item>
    <item>
      <title>Function Call 是什么</title>
      <link>https://tuanzi-wow.cn/agent/xiaolin-function-calling/</link>
      <pubDate>Sun, 06 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/agent/xiaolin-function-calling/</guid>
      <description>生成文本-Function_Call-操作外部程序……</description>
      <content:encoded><![CDATA[<h1 id="function-call是什么">Function Call是什么?</h1>
<h2 id="实现了从只会说话到能做事情">实现了从只会说话到能做事情</h2>
<p>生成文本-&gt;Function_Call-&gt;操作外部程序</p>
<h2 id="function-call的工作原理">Function Call的工作原理:</h2>
<p>分为四步:定义函数-&gt;选择函数(模型选择)-&gt;执行函数-&gt;返回结果(生成回答)</p>
<h3 id="定义函数">定义函数:</h3>
<p>用JSON格式描述:函数名称(name),功能说明(description),参数(params)</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;tools&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;function&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="s2">&#34;function&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;get_weather&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;获取指定城市的实时天气&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;parameters&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;object&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="s2">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;city&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">              <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">              <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;城市名称，比如：上海&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">          <span class="p">},</span>
</span></span><span class="line"><span class="cl">          <span class="s2">&#34;required&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;city&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="模型判断">模型判断:</h3>
<p>LLM分析意图并调用函数</p>
<h3 id="执行函数">执行函数</h3>
<p>LLM本身不执行函数,而是输出调用意图+函数参数,应用程序拿到指令后调用函数执行函数</p>
<h3 id="生成回答">生成回答</h3>
<p>LLM拿到结果并执行回答</p>
<h2 id="为什么function-call这么重要">为什么Function Call这么重要</h2>
<p>解决了两个问题:</p>
<ol>
<li>when:什么时候调用:LLM根据用户自然语言判断意图</li>
<li>传入什么参数:LLM从自然语言结构化传入参数</li>
</ol>
<p>最底层的技术基础</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
