<?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>Agent 学习笔记 on On My Way</title>
    <link>https://tuanzi-wow.cn/agent/</link>
    <description>Recent content in Agent 学习笔记 on On My Way</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <atom:link href="https://tuanzi-wow.cn/agent/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>Spring AI Tools</title>
      <link>https://tuanzi-wow.cn/agent/spring-ai-tools/</link>
      <pubDate>Sun, 06 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/agent/spring-ai-tools/</guid>
      <description>Tool是agents调用来执行操作的组件,通过定义良好的输入和输出来让模型和外部世界交互……</description>
      <content:encoded><![CDATA[<h1 id="tools">Tools</h1>
<h2 id="定义">定义:</h2>
<p>Tool是agents调用来执行操作的组件,通过<strong>定义良好的输入和输出</strong>来让模型和外部世界交互</p>
<p>Tools封装了一个可调用的函数及其输入模式,允许模型决定什么时候调用Tools以及传入的参数</p>
<p>Tool主要用语言:</p>
<ul>
<li>信息检索:与外部数据源进行交互检索信息,如数据库和Web搜索引擎.主要目标是增强model的知识,使其能够回答原本无法回答的问题</li>
<li>执行操作:目标是自动化原本需要人工干预或者显式编程的任务</li>
</ul>
<p>ps:Toolc calling称为model能力但是实际上由客户端提供ToolCalling逻辑</p>
<h2 id="quick-start">Quick Start</h2>
<p>两个示例:一个信息检索,一个执行操作</p>
<h3 id="信息检索">信息检索</h3>
<p>在DataTimeTool类中实现一个Tool来获取日期和时间(此处不关心具体实现方式)</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></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">import</span> <span class="n">java</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">LocalDateTime</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">annotation</span><span class="o">.</span><span class="n">Tool</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">i18n</span><span class="o">.</span><span class="n">LocaleContextHolder</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">DateTimeTools</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="err">@</span><span class="n">Tool</span><span class="p">(</span><span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;Get the current date and time in the user&#39;s timezone&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="ne">String</span> <span class="n">getCurrentDateTime</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="n">LocalDateTime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">atZone</span><span class="p">(</span><span class="n">LocaleContextHolder</span><span class="o">.</span><span class="n">getTimeZone</span><span class="p">()</span><span class="o">.</span><span class="n">toZoneId</span><span class="p">())</span><span class="o">.</span><span class="n">toString</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="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>如何让LLM了解到这个Tool的存在:通过调用Chatclient的tool()方法通知LLM
注意 tool(datetimetool)中的datetimetool需要实例化(也就你JAVA这么多事)</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></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">ChatModel</span> <span class="n">chatModel</span> <span class="o">=</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="ne">String</span> <span class="n">response</span> <span class="o">=</span> <span class="n">ChatClient</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">chatModel</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="o">.</span><span class="n">prompt</span><span class="p">(</span><span class="s2">&#34;What day is tomorrow?&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="o">.</span><span class="n">tools</span><span class="p">(</span><span class="n">new</span> <span class="n">DateTimeTools</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">      <span class="o">.</span><span class="n">call</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">      <span class="o">.</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span><span class="n">response</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="o">//</span> <span class="err">输出：</span><span class="n">Tomorrow</span> <span class="n">is</span> <span class="mi">2015</span><span class="o">-</span><span class="mi">10</span><span class="o">-</span><span class="mf">21.</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><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">import</span> <span class="n">java</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">LocalDateTime</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">java</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">format</span><span class="o">.</span><span class="n">DateTimeFormatter</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">annotation</span><span class="o">.</span><span class="n">Tool</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">i18n</span><span class="o">.</span><span class="n">LocaleContextHolder</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">DateTimeTools</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="err">@</span><span class="n">Tool</span><span class="p">(</span><span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;Get the current date and time in the user&#39;s timezone&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="ne">String</span> <span class="n">getCurrentDateTime</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="n">LocalDateTime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">atZone</span><span class="p">(</span><span class="n">LocaleContextHolder</span><span class="o">.</span><span class="n">getTimeZone</span><span class="p">()</span><span class="o">.</span><span class="n">toZoneId</span><span class="p">())</span><span class="o">.</span><span class="n">toString</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="err">@</span><span class="n">Tool</span><span class="p">(</span><span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;Set a user alarm for the given time, provided in ISO-8601 format&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="n">void</span> <span class="n">setAlarm</span><span class="p">(</span><span class="ne">String</span> <span class="n">time</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">LocalDateTime</span> <span class="n">alarmTime</span> <span class="o">=</span> <span class="n">LocalDateTime</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">DateTimeFormatter</span><span class="o">.</span><span class="n">ISO_DATE_TIME</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span><span class="s2">&#34;Alarm set for &#34;</span> <span class="o">+</span> <span class="n">alarmTime</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="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>那么有的同学就要问了:
这里只调用了datetimetool类而不是具体的工具,他是怎么知道选择哪个方法的
这就是你SpringAI叔叔的强大之处了,@Tool:会将该方法自动注册为一个tool
所以你们臭学JAVA的还不好好学Spring,Spring Boot,Spring MVC?</p>
<h3 id="概述">概述</h3>
<p><img alt="Tool Calling 主要操作序列" loading="lazy" src="https://java2ai.com/assets/images/tool-calling-01-f574ce40dfbd8203a4f5f0c08256258e.jpg"></p>
<p>1.Tool定义:名称,描述和传入参数
2.调用:Model发送带有Tool名称和参数的相应
3.通过名称选择tool并传入参数执行
4.toolcall结果由程序处理
5.结果传回Model
6.Model根据结果作为附加上下文生成最终响应</p>
<p>Tools 是 tool calling 的构建块，它们由 <code>ToolCallback</code> 接口建模。Spring AI 提供了从方法和函数指定 <code>ToolCallback</code>(s) 的内置支持，但您始终可以定义自己的 <code>ToolCallback</code> 实现以支持更多用例。</p>
<p><code>ChatModel</code> 实现透明地将 tool call 请求分派到相应的 <code>ToolCallback</code> 实现，并将 tool call 结果发送回 model，最终生成最终响应。它们使用 <code>ToolCallingManager</code> 接口来执行此操作，该接口负责管理 tool 执行生命周期。</p>
<p><code>ChatClient</code> 和 <code>ChatModel</code> 都接受 <code>ToolCallback</code> 对象列表，以使 tools 可用于 model 和最终执行它们的 <code>ToolCallingManager</code>。</p>
<p>除了直接传递 <code>ToolCallback</code> 对象外，您还可以传递 tool 名称列表，这些名称将使用 <code>ToolCallbackResolver</code> 接口动态解析。</p>
<h2 id="创建工具">创建工具</h2>
<p>Spring AI提供了两种从方法指定Tools(即ToolCallback(s))的内置支持</p>
<ul>
<li>声明式:使用@Tool注解</li>
<li>编程式:使用低级MethodToolCallback实现</li>
</ul>
<h3 id="方法作为tool">方法作为Tool</h3>
<h4 id="声明式规范-tool">声明式规范 @Tool</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></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 DateTimeTools {
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  @Tool(description = &#34;Get the current date and time in the user&#39;s timezone&#34;)
</span></span><span class="line"><span class="cl">  String getCurrentDateTime() {
</span></span><span class="line"><span class="cl">      return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></td></tr></table>
</div>
</div><p>@Tool注解允许你提供的信息:</p>
<ul>
<li>name:如果未提供,将使用方法名称</li>
<li>description:tool描述;若未提供,使用方法名称代替.但是强烈建议详细描述,对于model理解tool的用途以及when to use and how to use很重要</li>
<li>returnDirect:结果是否直接传回model;为布尔值</li>
<li>resultConverter:将toolcall的结果转化为String Object以 <code>ToolCallResultConverter</code> 实现</li>
</ul>
<p><strong>NOTE:</strong> Spring AI 为 <code>@Tool</code> 注解方法的 AOT 编译提供内置支持，只要包含方法的类是 Spring bean（例如 <code>@Component</code>）。否则，您需要向 GraalVM 编译器提供必要的配置。例如，通过用 <code>@RegisterReflection(memberCategories = MemberCategory.INVOKE_DECLARED_METHODS)</code> 注解类。</p>
<p>如果方法返回值，返回类型<strong>必须是可序列化类型</strong>，因为结果将被序列化并发送回 model。</p>
<p><code>@ToolParam</code> 注解可用于提供有关输入参数的附加信息，例如描述或参数是必需还是可选的。默认情况下，所有输入参数都被视为必需</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></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">import</span> <span class="n">java</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">LocalDateTime</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">java</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">format</span><span class="o">.</span><span class="n">DateTimeFormatter</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">annotation</span><span class="o">.</span><span class="n">Tool</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">annotation</span><span class="o">.</span><span class="n">ToolParam</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="n">DateTimeTools</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="err">@</span><span class="n">Tool</span><span class="p">(</span><span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;Set a user alarm for the given time&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="n">void</span> <span class="n">setAlarm</span><span class="p">(</span><span class="err">@</span><span class="n">ToolParam</span><span class="p">(</span><span class="n">description</span> <span class="o">=</span> <span class="s2">&#34;Time in ISO-8601 format&#34;</span><span class="p">)</span> <span class="ne">String</span> <span class="n">time</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">LocalDateTime</span> <span class="n">alarmTime</span> <span class="o">=</span> <span class="n">LocalDateTime</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">DateTimeFormatter</span><span class="o">.</span><span class="n">ISO_DATE_TIME</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span><span class="s2">&#34;Alarm set for &#34;</span> <span class="o">+</span> <span class="n">alarmTime</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="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>@ToolParam允许你提供的有关tool参数的关键信息:</p>
<ul>
<li><code>description</code>：参数的描述，model 可以使用它来更好地理解如何使用它。例如，参数应该是什么格式，允许什么值等。</li>
<li><code>required</code>：参数是必需还是可选的。默认情况下，所有参数都被视为必需。</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Spring AI Tool Calling 使用指南</title>
      <link>https://tuanzi-wow.cn/agent/spring-ai-tool-calling/</link>
      <pubDate>Sun, 06 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/agent/spring-ai-tool-calling/</guid>
      <description>ToolCalling(FunctionCalling)允许模型与一组API或者工具进行交互,增强模型的能力……</description>
      <content:encoded><![CDATA[<h1 id="spring-ai-tool-calling使用指南之我不用java好多年">Spring AI Tool Calling使用指南之我不用JAVA好多年</h1>
<h2 id="概述">概述:</h2>
<p>Tool Calling(Function Calling)允许模型与一组API或者工具进行交互,增强模型的能力</p>
<p>主要功能:</p>
<ul>
<li>信息检索:从外部数据源获取信息,比如:数据库,Web服务,例如:Web_Search</li>
<li>执行操作:在软件系统执行特定操作:例如:预定航班,生成代码</li>
</ul>
<p>Spring AI Alibaba拓展服务:</p>
<ul>
<li>搜索引擎</li>
<li>翻译服务</li>
<li>地图服务</li>
<li>数据服务</li>
<li>开发工具</li>
<li>其他工具</li>
</ul>
<h2 id="详细使用说明">详细使用说明</h2>
<h2 id="python-tool示例你个臭执行python代码的"><strong>Python Tool示例</strong>(你个臭执行Python代码的)</h2>
<p><code>PythonTool</code> 使用 GraalVM polyglot 在沙箱环境中执行 Python 代码。这个工具允许 AI 代理执行 Python 代码片段并获取结果。</p>
<h3 id="依赖配置">依赖配置:</h3>
<p>使用Maven添加依赖:</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></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="o">&lt;</span><span class="n">dependency</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="o">&lt;</span><span class="n">groupId</span><span class="o">&gt;</span><span class="n">com</span><span class="o">.</span><span class="n">alibaba</span><span class="o">.</span><span class="n">cloud</span><span class="o">.</span><span class="n">ai</span><span class="o">&lt;/</span><span class="n">groupId</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="o">&lt;</span><span class="n">artifactId</span><span class="o">&gt;</span><span class="n">spring</span><span class="o">-</span><span class="n">ai</span><span class="o">-</span><span class="n">alibaba</span><span class="o">-</span><span class="n">starter</span><span class="o">-</span><span class="k">tool</span><span class="o">-</span><span class="n">calling</span><span class="o">-</span><span class="n">python</span><span class="o">&lt;/</span><span class="n">artifactId</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="o">&lt;</span><span class="n">version</span><span class="o">&gt;$</span><span class="p">{</span><span class="n">version</span><span class="p">}</span><span class="o">&lt;/</span><span class="n">version</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;/</span><span class="n">dependency</span><span class="o">&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>注意</strong>：Python Tool 需要 GraalVM polyglot 依赖，这些依赖已作为可选依赖包含。如果需要使用，请确保 GraalVM polyglot 在 classpath 中。</p>
<h3 id="自动配置">自动配置</h3>
<p>Python Tool默认启用,会自动注册为ToolCallback并可供AI代理使用,如果需要禁用,可以在配置文件中设置</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="n">spring</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="n">ai</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="n">alibaba</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">			<span class="n">python</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">				<span class="k">tool</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">					<span class="n">enabled</span><span class="p">:</span> <span class="bp">false</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="基本使用">基本使用</h3>
<h4 id="示例1在chatclient中使用">示例1:在ChatClient中使用</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></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">import</span> <span class="n">com</span><span class="o">.</span><span class="n">alibaba</span><span class="o">.</span><span class="n">cloud</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">agent</span><span class="o">.</span><span class="n">python</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">PythonTool</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">ChatClient</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">ChatModel</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">beans</span><span class="o">.</span><span class="n">factory</span><span class="o">.</span><span class="n">annotation</span><span class="o">.</span><span class="n">Autowired</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">stereotype</span><span class="o">.</span><span class="n">Service</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">Service</span>
</span></span><span class="line"><span class="cl"><span class="n">public</span> <span class="k">class</span> <span class="n">PythonToolService</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="err">@</span><span class="n">Autowired</span>
</span></span><span class="line"><span class="cl">    <span class="n">private</span> <span class="n">ChatModel</span> <span class="n">chatModel</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="err">@</span><span class="n">Autowired</span>
</span></span><span class="line"><span class="cl">    <span class="n">private</span> <span class="n">PythonTool</span> <span class="n">pythonTool</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">public</span> <span class="ne">String</span> <span class="n">executeCalculation</span><span class="p">(</span><span class="ne">String</span> <span class="n">question</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="o">//</span> <span class="err">创建</span> <span class="n">ChatClient</span> <span class="err">并添加</span> <span class="n">Python</span> <span class="n">Tool</span>
</span></span><span class="line"><span class="cl">        <span class="n">ChatClient</span> <span class="n">chatClient</span> <span class="o">=</span> <span class="n">ChatClient</span><span class="o">.</span><span class="n">builder</span><span class="p">(</span><span class="n">chatModel</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">tools</span><span class="p">(</span><span class="n">pythonTool</span><span class="o">.</span><span class="n">createPythonToolCallback</span><span class="p">(</span><span class="n">PythonTool</span><span class="o">.</span><span class="n">DESCRIPTION</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">build</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="o">//</span> <span class="err">使用工具进行对话</span>
</span></span><span class="line"><span class="cl">        <span class="ne">String</span> <span class="n">response</span> <span class="o">=</span> <span class="n">chatClient</span><span class="o">.</span><span class="n">prompt</span><span class="p">(</span><span class="n">question</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">call</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">content</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">response</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><h4 id="示例2直接使用pythontool">示例2:直接使用PythonTool</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></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">import</span> <span class="n">com</span><span class="o">.</span><span class="n">alibaba</span><span class="o">.</span><span class="n">cloud</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">agent</span><span class="o">.</span><span class="n">python</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">PythonTool</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">ToolContext</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">public</span> <span class="k">class</span> <span class="n">DirectPythonToolUsage</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">public</span> <span class="n">void</span> <span class="n">executePythonCode</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">PythonTool</span> <span class="n">pythonTool</span> <span class="o">=</span> <span class="n">new</span> <span class="n">PythonTool</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="o">//</span> <span class="err">创建请求</span>
</span></span><span class="line"><span class="cl">        <span class="n">PythonTool</span><span class="o">.</span><span class="n">PythonRequest</span> <span class="n">request</span> <span class="o">=</span> <span class="n">new</span> <span class="n">PythonTool</span><span class="o">.</span><span class="n">PythonRequest</span><span class="p">(</span><span class="s2">&#34;2 + 2&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="o">//</span> <span class="err">执行</span> <span class="n">Python</span> <span class="err">代码</span>
</span></span><span class="line"><span class="cl">        <span class="ne">String</span> <span class="n">result</span> <span class="o">=</span> <span class="n">pythonTool</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">new</span> <span class="n">ToolContext</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span><span class="s2">&#34;Result: &#34;</span> <span class="o">+</span> <span class="n">result</span><span class="p">);</span> <span class="o">//</span> <span class="err">输出</span><span class="p">:</span> <span class="n">Result</span><span class="p">:</span> <span class="mi">4</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><h4 id="示例3执行复杂计算">示例3:执行复杂计算</h4>
<p>还是通过在client中调用PythonTool</p>
<h4 id="示例4字符串操作">示例4:字符串操作</h4>
<p>类似于示例2:创建request,调用apply(request,toolcontext)</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-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl">  <span class="n">PythonTool</span><span class="o">.</span><span class="n">PythonRequest</span> <span class="n">request1</span> <span class="o">=</span> <span class="n">new</span> <span class="n">PythonTool</span><span class="o">.</span><span class="n">PythonRequest</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;&#39;Hello, &#39; + &#39;World&#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="ne">String</span> <span class="n">result1</span> <span class="o">=</span> <span class="n">pythonTool</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">request1</span><span class="p">,</span> <span class="n">toolContext</span><span class="p">);</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="示例5在spring-boot应用中使用">示例5:在Spring Boot应用中使用</h4>
<p>类似于示例1
创建client并将PythonTool写入,只是这里的1应用场景是Spring Boot</p>
<h4 id="示例6自定义toolcallback">示例6:自定义ToolCallback</h4>
<p>(来你告诉我这不是在Spring Boot里面运行吗?)</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></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">import</span> <span class="n">com</span><span class="o">.</span><span class="n">alibaba</span><span class="o">.</span><span class="n">cloud</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">agent</span><span class="o">.</span><span class="n">python</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">PythonTool</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">ToolCallback</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">annotation</span><span class="o">.</span><span class="n">Bean</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">annotation</span><span class="o">.</span><span class="n">Configuration</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">Configuration</span>
</span></span><span class="line"><span class="cl"><span class="n">public</span> <span class="k">class</span> <span class="n">PythonToolConfiguration</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="err">@</span><span class="n">Bean</span>
</span></span><span class="line"><span class="cl">    <span class="n">public</span> <span class="n">PythonTool</span> <span class="n">pythonTool</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">new</span> <span class="n">PythonTool</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="err">@</span><span class="n">Bean</span>
</span></span><span class="line"><span class="cl">    <span class="n">public</span> <span class="n">ToolCallback</span> <span class="n">pythonToolCallback</span><span class="p">(</span><span class="n">PythonTool</span> <span class="n">pythonTool</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">PythonTool</span><span class="o">.</span><span class="n">createPythonToolCallback</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;执行 Python 代码并返回结果。支持数学计算、字符串处理、列表操作等。&#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="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="示例7多工具组合使用">示例7:多工具组合使用</h4>
<p>PythonTool和其他Tool一起调用,看看就好,也是创建client并添加tools,这次是多个</p>
<h3 id="安全特性">安全特性:</h3>
<p>PythonTool在沙箱环境中运行,具有以下的安全限制</p>
<ul>
<li>文件I/O已禁用:无法读写文件</li>
<li>本地访问已禁用:无法访问本地系统资源</li>
<li>进程创建已禁用:无法创建新的进程</li>
<li>默认限制所有访问:所有访问受限</li>
</ul>
<p>保证了Python代码执行的安全性</p>
<h3 id="支持的数据类型">支持的数据类型</h3>
<ul>
<li>字符串:直接返回</li>
<li>数字:转化为字符串返回</li>
<li>布尔值:转化为字符串返回</li>
<li>数组/列表:转化为字符串表现形式</li>
<li>其他类型:使用toString()方法转换</li>
</ul>
<h3 id="注意事项">注意事项</h3>
<ol>
<li><strong>GraalVM 依赖</strong>：确保 GraalVM polyglot 依赖在 classpath 中</li>
<li><strong>性能考虑</strong>：每次执行都会创建新的 Context，对于频繁调用可能需要优化</li>
<li><strong>错误处理</strong>：代码执行错误会被捕获并返回错误消息</li>
<li><strong>代码限制</strong>：由于安全限制，某些 Python 功能可能不可用</li>
<li><strong>资源管理</strong>：Context 会自动关闭，无需手动管理</li>
</ol>
<h3 id="一个完整的示例ai代理使用python-tool">一个完整的示例:AI代理使用Python Tool:</h3>
<p>eee,这算哪门子示例,好吧也算</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></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">import</span> <span class="n">com</span><span class="o">.</span><span class="n">alibaba</span><span class="o">.</span><span class="n">cloud</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">agent</span><span class="o">.</span><span class="n">python</span><span class="o">.</span><span class="k">tool</span><span class="o">.</span><span class="n">PythonTool</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">ChatClient</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">ai</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">ChatModel</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">import</span> <span class="n">org</span><span class="o">.</span><span class="n">springframework</span><span class="o">.</span><span class="n">stereotype</span><span class="o">.</span><span class="n">Service</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">Service</span>
</span></span><span class="line"><span class="cl"><span class="n">public</span> <span class="k">class</span> <span class="n">PythonToolAgentService</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">private</span> <span class="n">final</span> <span class="n">ChatClient</span> <span class="n">chatClient</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">public</span> <span class="n">PythonToolAgentService</span><span class="p">(</span><span class="n">ChatModel</span> <span class="n">chatModel</span><span class="p">,</span> <span class="n">PythonTool</span> <span class="n">pythonTool</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">this</span><span class="o">.</span><span class="n">chatClient</span> <span class="o">=</span> <span class="n">ChatClient</span><span class="o">.</span><span class="n">builder</span><span class="p">(</span><span class="n">chatModel</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">tools</span><span class="p">(</span><span class="n">pythonTool</span><span class="o">.</span><span class="n">createPythonToolCallback</span><span class="p">(</span><span class="n">PythonTool</span><span class="o">.</span><span class="n">DESCRIPTION</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">build</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">public</span> <span class="ne">String</span> <span class="n">solveMathProblem</span><span class="p">(</span><span class="ne">String</span> <span class="n">problem</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="ne">String</span> <span class="n">prompt</span> <span class="o">=</span> <span class="ne">String</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">            请使用 Python 工具解决以下数学问题：
</span></span></span><span class="line"><span class="cl"><span class="s2">            </span><span class="si">%s</span><span class="s2">
</span></span></span><span class="line"><span class="cl"><span class="s2">            
</span></span></span><span class="line"><span class="cl"><span class="s2">            请展示计算过程。
</span></span></span><span class="line"><span class="cl"><span class="s2">            &#34;&#34;&#34;</span><span class="p">,</span> <span class="n">problem</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">chatClient</span><span class="o">.</span><span class="n">prompt</span><span class="p">(</span><span class="n">prompt</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">call</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">content</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">public</span> <span class="ne">String</span> <span class="n">analyzeData</span><span class="p">(</span><span class="ne">String</span> <span class="n">dataDescription</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="ne">String</span> <span class="n">prompt</span> <span class="o">=</span> <span class="ne">String</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">            请使用 Python 工具分析以下数据：
</span></span></span><span class="line"><span class="cl"><span class="s2">            </span><span class="si">%s</span><span class="s2">
</span></span></span><span class="line"><span class="cl"><span class="s2">            
</span></span></span><span class="line"><span class="cl"><span class="s2">            请计算基本统计信息（平均值、中位数、标准差等）。
</span></span></span><span class="line"><span class="cl"><span class="s2">            &#34;&#34;&#34;</span><span class="p">,</span> <span class="n">dataDescription</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">chatClient</span><span class="o">.</span><span class="n">prompt</span><span class="p">(</span><span class="n">prompt</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">call</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="o">.</span><span class="n">content</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><a href="https://java2ai.com/integration/toolcalls/tool-calls#%E7%9B%AE%E5%BD%95">https://java2ai.com/integration/toolcalls/tool-calls#%E7%9B%AE%E5%BD%95</a>
自己去这里看</p>
<h3 id="使用说明">使用说明</h3>
<p>所有的Tool Calling实现都遵循相同的使用模式</p>
<ol>
<li>添加依赖:在pom.xml或者build.gradle中添加相应的依赖</li>
<li>自动配置:Spring Boot的生态真实太好用了,你们知道吗?<strong>会自动注册为ToolCallback</strong></li>
<li>在Chatclient中使用:通过ChatClient.builder().tools()添加工具</li>
<li>AI模型调用:AI模型会根据会话内容自动决定是否调用工具</li>
</ol>
<h3 id="通用接口">通用接口</h3>
<p>你这么好用你不早说?</p>
<p>所有 Tool 都实现了 <code>BiFunction&lt;Request, ToolContext, String&gt;</code> 接口，并通过 <code>FunctionToolCallback</code> 包装为 <code>ToolCallback</code>：</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">interface</span> <span class="nc">ToolCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">String</span><span class="w"> </span><span class="nf">getName</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">String</span><span class="w"> </span><span class="nf">getDescription</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">ToolResponse</span><span class="w"> </span><span class="nf">call</span><span class="p">(</span><span class="n">ToolRequest</span><span class="w"> </span><span class="n">request</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="配置说明">配置说明</h3>
<p>大多数工具都支持通过Spring Boot配置属性进行配置(又是你宝宝)</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="n">spring</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="n">ai</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">alibaba</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="k">tool</span><span class="o">-</span><span class="n">name</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">enabled</span><span class="p">:</span> <span class="bp">true</span>  <span class="c1"># 启用/禁用工具</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 其他工具特定配置</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="认证和api-key">认证和API key</h3>
<p>参考各个工具的文档</p>
<h3 id="最佳实践">最佳实践</h3>
<ol>
<li><strong>工具选择</strong>：根据实际需求选择合适的工具，避免添加不必要的工具</li>
<li><strong>错误处理</strong>：工具调用可能失败，确保有适当的错误处理机制</li>
<li><strong>性能优化</strong>：对于频繁调用的工具，考虑缓存结果</li>
<li><strong>安全性</strong>：确保 API Key 等敏感信息的安全存储</li>
<li><strong>成本控制</strong>：某些工具（如搜索、翻译）可能产生费用，注意使用量</li>
</ol>
]]></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>
