import{s as CM,n as oM,o as iM}from"../chunks/scheduler.505acc25.js";import{S as AM,i as cM,e as j,s as t,c as y,h as mM,a as e,d as s,b as n,f as wM,g as U,j as J,k as pM,l as hM,m as a,n as T,t as w,o as p,p as I}from"../chunks/index.b1175496.js";import{C as bM,H as K}from"../chunks/Heading.eda51538.js";import{C as IM}from"../chunks/CodeBlock.9d480d26.js";import{E as uM}from"../chunks/MermaidChart.svelte_svelte_type_style_lang.ea377ea6.js";function rM(Yl){let C,Ml,O,sl,o,al,i,tl,A,Rl="现在你已经探索了智能体 AI 在游戏中的潜力和局限性，是时候亲自动手了。在本节中，你将<strong>构建自己的 AI 智能体来进行宝可梦风格的回合制战斗</strong>，使用你在整个课程中学到的一切知识。",nl,c,Xl="我们将把系统分解为四个关键构建块：",jl,m,xl="<li><p><strong>Poke-env:</strong> 一个专为训练基于规则或强化学习的宝可梦机器人而设计的 Python 库。</p></li> <li><p><strong>Pokémon Showdown:</strong> 一个在线对战模拟器，你的智能体将在这里战斗。</p></li> <li><p><strong>LLMAgentBase:</strong> 我们构建的一个自定义 Python 类，用于将你的 LLM 与 Poke-env 战斗环境连接。</p></li> <li><p><strong>TemplateAgent:</strong> 一个起始模板，你将完善它来创建自己独特的战斗智能体。</p></li>",el,h,Fl="让我们详细探索这些组件。",Jl,b,yl,u,zl='<img src="https://github.com/hsahovic/poke-env/raw/master/rl-gif.gif" alt="Battle gif"/>',Ul,r,ql=`<a href="https://github.com/hsahovic/poke-env" rel="nofollow">Poke-env</a>是一个 Python 接口，最初由<a href="https://huggingface.co/hsahovic" rel="nofollow">Haris Sahovic</a>构建用于训练强化学习机器人，但我们已将其重新用于智能体 AI。
它允许你的智能体通过简单的 API 与 Pokémon Showdown 交互。`,Tl,d,Hl="它提供了一个<code>Player</code>类，你的智能体将继承该类，涵盖与图形界面通信所需的一切。",wl,f,Ll='<strong>文档</strong>: <a href="https://poke-env.readthedocs.io/en/stable/" rel="nofollow">poke-env.readthedocs.io</a><br/> <strong>代码库</strong>: <a href="https://github.com/hsahovic/poke-env" rel="nofollow">github.com/hsahovic/poke-env</a>',pl,_,Il,B,$l=`<a href="https://pokemonshowdown.com/" rel="nofollow">Pokémon Showdown</a>是一个<a href="https://github.com/smogon/Pokemon-Showdown" rel="nofollow">开源</a>战斗模拟器，你的智能体将在这里进行实时宝可梦战斗。
它提供了一个完整的界面来实时模拟和显示战斗。在我们的挑战中，你的机器人将像人类玩家一样行动，逐回合选择招式。`,Cl,Z,Pl="我们已经部署了一个所有参与者都将使用的服务器来进行战斗。让我们看看谁能构建出最好的 AI 战斗智能体！",ol,G,Dl='<strong>代码库</strong>: <a href="https://github.com/smogon/Pokemon-Showdown" rel="nofollow">github.com/smogon/Pokemon-Showdown</a><br/> <strong>网站</strong>: <a href="https://pokemonshowdown.com/" rel="nofollow">pokemonshowdown.com</a>',il,v,Al,N,Kl=`<code>LLMAgentBase</code>是一个扩展了<strong>Poke-env</strong>中<code>Player</code>类的 Python 类。
它作为你的<strong>LLM</strong>和<strong>宝可梦战斗模拟器</strong>之间的桥梁，处理输入/输出格式化并维护战斗上下文。`,cl,k,Ol="这个基础智能体提供了一组工具（定义在<code>STANDARD_TOOL_SCHEMA</code>中）来与环境交互，包括：",ml,E,lM="<li><code>choose_move</code>: 用于在战斗中选择攻击</li> <li><code>choose_switch</code>: 用于切换宝可梦</li>",hl,V,MM="LLM 应该使用这些工具在比赛中做出决策。",bl,W,ul,g,sM="<li><code>choose_move(battle: Battle)</code>: 这是每回合调用的主要方法。它接收一个<code>Battle</code>对象并基于 LLM 的输出返回一个动作字符串。</li>",rl,S,dl,Q,aM="<li><p><code>_format_battle_state(battle)</code>: 将当前战斗状态转换为字符串，使其适合发送给 LLM。</p></li> <li><p><code>_find_move_by_name(battle, move_name)</code>: 按名称查找招式，用于 LLM 响应中调用<code>choose_move</code>。</p></li> <li><p><code>_find_pokemon_by_name(battle, pokemon_name)</code>: 根据 LLM 的切换命令定位要切换到的特定宝可梦。</p></li> <li><p><code>_get_llm_decision(battle_state)</code>: 这个方法在基类中是抽象的。你需要在自己的智能体中实现它（见下一节），在那里你定义如何查询 LLM 并解析其响应。</p></li>",fl,Y,tM="这里是显示决策如何工作的摘录：",_l,R,Bl,X,nM='<strong>完整源代码</strong>: <a href="https://huggingface.co/spaces/Jofthomas/twitch_streaming/blob/main/agents.py" rel="nofollow">agents.py</a>',Zl,x,Gl,F,jM="现在到了有趣的部分！以 LLMAgentBase 作为你的基础，是时候实现你自己的智能体了，用你自己的策略登上排行榜。",vl,z,eM='你将从这个模板开始并构建自己的逻辑。我们还提供了三个使用<strong>OpenAI</strong>、<strong>Mistral</strong>和<strong>Gemini</strong>模型的<a href="https://huggingface.co/spaces/Jofthomas/twitch_streaming/blob/main/agents.py" rel="nofollow">完整示例</a>来指导你。',Nl,q,JM="这是模板的简化版本：",kl,H,El,L,yM="这段代码无法直接运行，它是你自定义逻辑的蓝图。",Vl,$,UM="有了所有准备好的组件，现在轮到你构建一个有竞争力的智能体了。在下一节中，我们将展示如何将你的智能体部署到我们的服务器并与其他智能体实时对战。",Wl,P,TM="让战斗开始吧！🔥",gl,D,Sl,ll,Ql;return o=new bM({props:{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"}}),i=new K({props:{title:"构建你自己的宝可梦对战智能体",local:"构建你自己的宝可梦对战智能体",headingTag:"h1"}}),b=new K({props:{title:"🧠 Poke-env",local:"-poke-env",headingTag:"h2"}}),_=new K({props:{title:"⚔️ Pokémon Showdown",local:"-pokémon-showdown",headingTag:"h2"}}),v=new K({props:{title:"🔌 LLMAgentBase",local:"-llmagentbase",headingTag:"h2"}}),W=new K({props:{title:"🧠 核心逻辑",local:"-核心逻辑",headingTag:"h3"}}),S=new K({props:{title:"🔧 关键内部方法",local:"-关键内部方法",headingTag:"h3"}}),R=new IM({props:{code:" ",highlighted:`STANDARD_TOOL_SCHEMA = {
    <span class="hljs-string">&quot;choose_move&quot;</span>: {
        ...
    },
    <span class="hljs-string">&quot;choose_switch&quot;</span>: {
        ...
    },
}

<span class="hljs-keyword">class</span> <span class="hljs-title class_">LLMAgentBase</span>(<span class="hljs-title class_ inherited__">Player</span>):
    <span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self, *args, **kwargs</span>):
        <span class="hljs-built_in">super</span>().__init__(*args, **kwargs)
        self.standard_tools = STANDARD_TOOL_SCHEMA
        self.battle_history = []

    <span class="hljs-keyword">def</span> <span class="hljs-title function_">_format_battle_state</span>(<span class="hljs-params">self, battle: Battle</span>) -&gt; <span class="hljs-built_in">str</span>:
        active_pkmn = battle.active_pokemon
        active_pkmn_info = <span class="hljs-string">f&quot;Your active Pokemon: <span class="hljs-subst">{active_pkmn.species}</span> &quot;</span> \\
                           <span class="hljs-string">f&quot;(Type: <span class="hljs-subst">{<span class="hljs-string">&#x27;/&#x27;</span>.join(<span class="hljs-built_in">map</span>(<span class="hljs-built_in">str</span>, active_pkmn.types))}</span>) &quot;</span> \\
                           <span class="hljs-string">f&quot;HP: <span class="hljs-subst">{active_pkmn.current_hp_fraction * <span class="hljs-number">100</span>:<span class="hljs-number">.1</span>f}</span>% &quot;</span> \\
                           <span class="hljs-string">f&quot;Status: <span class="hljs-subst">{active_pkmn.status.name <span class="hljs-keyword">if</span> active_pkmn.status <span class="hljs-keyword">else</span> <span class="hljs-string">&#x27;None&#x27;</span>}</span> &quot;</span> \\
                           <span class="hljs-string">f&quot;Boosts: <span class="hljs-subst">{active_pkmn.boosts}</span>&quot;</span>

        opponent_pkmn = battle.opponent_active_pokemon
        opp_info_str = <span class="hljs-string">&quot;Unknown&quot;</span>
        <span class="hljs-keyword">if</span> opponent_pkmn:
            opp_info_str = <span class="hljs-string">f&quot;<span class="hljs-subst">{opponent_pkmn.species}</span> &quot;</span> \\
                           <span class="hljs-string">f&quot;(Type: <span class="hljs-subst">{<span class="hljs-string">&#x27;/&#x27;</span>.join(<span class="hljs-built_in">map</span>(<span class="hljs-built_in">str</span>, opponent_pkmn.types))}</span>) &quot;</span> \\
                           <span class="hljs-string">f&quot;HP: <span class="hljs-subst">{opponent_pkmn.current_hp_fraction * <span class="hljs-number">100</span>:<span class="hljs-number">.1</span>f}</span>% &quot;</span> \\
                           <span class="hljs-string">f&quot;Status: <span class="hljs-subst">{opponent_pkmn.status.name <span class="hljs-keyword">if</span> opponent_pkmn.status <span class="hljs-keyword">else</span> <span class="hljs-string">&#x27;None&#x27;</span>}</span> &quot;</span> \\
                           <span class="hljs-string">f&quot;Boosts: <span class="hljs-subst">{opponent_pkmn.boosts}</span>&quot;</span>
        opponent_pkmn_info = <span class="hljs-string">f&quot;Opponent&#x27;s active Pokemon: <span class="hljs-subst">{opp_info_str}</span>&quot;</span>

        available_moves_info = <span class="hljs-string">&quot;Available moves:\\n&quot;</span>
        <span class="hljs-keyword">if</span> battle.available_moves:
            available_moves_info += <span class="hljs-string">&quot;\\n&quot;</span>.join(
                [<span class="hljs-string">f&quot;- <span class="hljs-subst">{move.<span class="hljs-built_in">id</span>}</span> (Type: <span class="hljs-subst">{move.<span class="hljs-built_in">type</span>}</span>, BP: <span class="hljs-subst">{move.base_power}</span>, Acc: <span class="hljs-subst">{move.accuracy}</span>, PP: <span class="hljs-subst">{move.current_pp}</span>/<span class="hljs-subst">{move.max_pp}</span>, Cat: <span class="hljs-subst">{move.category.name}</span>)&quot;</span>
                 <span class="hljs-keyword">for</span> move <span class="hljs-keyword">in</span> battle.available_moves]
            )
        <span class="hljs-keyword">else</span>:
             available_moves_info += <span class="hljs-string">&quot;- None (Must switch or Struggle)&quot;</span>

        available_switches_info = <span class="hljs-string">&quot;Available switches:\\n&quot;</span>
        <span class="hljs-keyword">if</span> battle.available_switches:
              available_switches_info += <span class="hljs-string">&quot;\\n&quot;</span>.join(
                  [<span class="hljs-string">f&quot;- <span class="hljs-subst">{pkmn.species}</span> (HP: <span class="hljs-subst">{pkmn.current_hp_fraction * <span class="hljs-number">100</span>:<span class="hljs-number">.1</span>f}</span>%, Status: <span class="hljs-subst">{pkmn.status.name <span class="hljs-keyword">if</span> pkmn.status <span class="hljs-keyword">else</span> <span class="hljs-string">&#x27;None&#x27;</span>}</span>)&quot;</span>
                   <span class="hljs-keyword">for</span> pkmn <span class="hljs-keyword">in</span> battle.available_switches]
              )
        <span class="hljs-keyword">else</span>:
            available_switches_info += <span class="hljs-string">&quot;- None&quot;</span>

        state_str = <span class="hljs-string">f&quot;<span class="hljs-subst">{active_pkmn_info}</span>\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;<span class="hljs-subst">{opponent_pkmn_info}</span>\\n\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;<span class="hljs-subst">{available_moves_info}</span>\\n\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;<span class="hljs-subst">{available_switches_info}</span>\\n\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;Weather: <span class="hljs-subst">{battle.weather}</span>\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;Terrains: <span class="hljs-subst">{battle.fields}</span>\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;Your Side Conditions: <span class="hljs-subst">{battle.side_conditions}</span>\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;Opponent Side Conditions: <span class="hljs-subst">{battle.opponent_side_conditions}</span>&quot;</span>
        <span class="hljs-keyword">return</span> state_str.strip()

    <span class="hljs-keyword">def</span> <span class="hljs-title function_">_find_move_by_name</span>(<span class="hljs-params">self, battle: Battle, move_name: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-type">Optional</span>[Move]:
        normalized_name = normalize_name(move_name)
        <span class="hljs-comment"># 优先精确ID匹配</span>
        <span class="hljs-keyword">for</span> move <span class="hljs-keyword">in</span> battle.available_moves:
            <span class="hljs-keyword">if</span> move.<span class="hljs-built_in">id</span> == normalized_name:
                <span class="hljs-keyword">return</span> move
        <span class="hljs-comment"># 后备方案: 检查显示名称（不太可靠）</span>
        <span class="hljs-keyword">for</span> move <span class="hljs-keyword">in</span> battle.available_moves:
            <span class="hljs-keyword">if</span> move.name.lower() == move_name.lower():
                <span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Warning: Matched move by display name &#x27;<span class="hljs-subst">{move.name}</span>&#x27; instead of ID &#x27;<span class="hljs-subst">{move.<span class="hljs-built_in">id</span>}</span>&#x27;. Input was &#x27;<span class="hljs-subst">{move_name}</span>&#x27;.&quot;</span>)
                <span class="hljs-keyword">return</span> move
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

    <span class="hljs-keyword">def</span> <span class="hljs-title function_">_find_pokemon_by_name</span>(<span class="hljs-params">self, battle: Battle, pokemon_name: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-type">Optional</span>[Pokemon]:
        normalized_name = normalize_name(pokemon_name)
        <span class="hljs-keyword">for</span> pkmn <span class="hljs-keyword">in</span> battle.available_switches:
            <span class="hljs-comment"># 规范化种类名称用于比较</span>
            <span class="hljs-keyword">if</span> normalize_name(pkmn.species) == normalized_name:
                <span class="hljs-keyword">return</span> pkmn
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

    <span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">choose_move</span>(<span class="hljs-params">self, battle: Battle</span>) -&gt; <span class="hljs-built_in">str</span>:
        battle_state_str = self._format_battle_state(battle)
        decision_result = <span class="hljs-keyword">await</span> self._get_llm_decision(battle_state_str)
        <span class="hljs-built_in">print</span>(decision_result)
        decision = decision_result.get(<span class="hljs-string">&quot;decision&quot;</span>)
        error_message = decision_result.get(<span class="hljs-string">&quot;error&quot;</span>)
        action_taken = <span class="hljs-literal">False</span>
        fallback_reason = <span class="hljs-string">&quot;&quot;</span>

        <span class="hljs-keyword">if</span> decision:
            function_name = decision.get(<span class="hljs-string">&quot;name&quot;</span>)
            args = decision.get(<span class="hljs-string">&quot;arguments&quot;</span>, {})
            <span class="hljs-keyword">if</span> function_name == <span class="hljs-string">&quot;choose_move&quot;</span>:
                move_name = args.get(<span class="hljs-string">&quot;move_name&quot;</span>)
                <span class="hljs-keyword">if</span> move_name:
                    chosen_move = self._find_move_by_name(battle, move_name)
                    <span class="hljs-keyword">if</span> chosen_move <span class="hljs-keyword">and</span> chosen_move <span class="hljs-keyword">in</span> battle.available_moves:
                        action_taken = <span class="hljs-literal">True</span>
                        chat_msg = <span class="hljs-string">f&quot;AI Decision: Using move &#x27;<span class="hljs-subst">{chosen_move.<span class="hljs-built_in">id</span>}</span>&#x27;.&quot;</span>
                        <span class="hljs-built_in">print</span>(chat_msg)
                        <span class="hljs-keyword">return</span> self.create_order(chosen_move)
                    <span class="hljs-keyword">else</span>:
                        fallback_reason = <span class="hljs-string">f&quot;LLM chose unavailable/invalid move &#x27;<span class="hljs-subst">{move_name}</span>&#x27;.&quot;</span>
                <span class="hljs-keyword">else</span>:
                     fallback_reason = <span class="hljs-string">&quot;LLM &#x27;choose_move&#x27; called without &#x27;move_name&#x27;.&quot;</span>
            <span class="hljs-keyword">elif</span> function_name == <span class="hljs-string">&quot;choose_switch&quot;</span>:
                pokemon_name = args.get(<span class="hljs-string">&quot;pokemon_name&quot;</span>)
                <span class="hljs-keyword">if</span> pokemon_name:
                    chosen_switch = self._find_pokemon_by_name(battle, pokemon_name)
                    <span class="hljs-keyword">if</span> chosen_switch <span class="hljs-keyword">and</span> chosen_switch <span class="hljs-keyword">in</span> battle.available_switches:
                        action_taken = <span class="hljs-literal">True</span>
                        chat_msg = <span class="hljs-string">f&quot;AI Decision: Switching to &#x27;<span class="hljs-subst">{chosen_switch.species}</span>&#x27;.&quot;</span>
                        <span class="hljs-built_in">print</span>(chat_msg)
                        <span class="hljs-keyword">return</span> self.create_order(chosen_switch)
                    <span class="hljs-keyword">else</span>:
                        fallback_reason = <span class="hljs-string">f&quot;LLM chose unavailable/invalid switch &#x27;<span class="hljs-subst">{pokemon_name}</span>&#x27;.&quot;</span>
                <span class="hljs-keyword">else</span>:
                    fallback_reason = <span class="hljs-string">&quot;LLM &#x27;choose_switch&#x27; called without &#x27;pokemon_name&#x27;.&quot;</span>
            <span class="hljs-keyword">else</span>:
                fallback_reason = <span class="hljs-string">f&quot;LLM called unknown function &#x27;<span class="hljs-subst">{function_name}</span>&#x27;.&quot;</span>

        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> action_taken:
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> fallback_reason:
                 <span class="hljs-keyword">if</span> error_message:
                     fallback_reason = <span class="hljs-string">f&quot;API Error: <span class="hljs-subst">{error_message}</span>&quot;</span>
                 <span class="hljs-keyword">elif</span> decision <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
                      fallback_reason = <span class="hljs-string">&quot;LLM did not provide a valid function call.&quot;</span>
                 <span class="hljs-keyword">else</span>:
                      fallback_reason = <span class="hljs-string">&quot;Unknown error processing LLM decision.&quot;</span>

            <span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Warning: <span class="hljs-subst">{fallback_reason}</span> Choosing random action.&quot;</span>)

            <span class="hljs-keyword">if</span> battle.available_moves <span class="hljs-keyword">or</span> battle.available_switches:
                 <span class="hljs-keyword">return</span> self.choose_random_move(battle)
            <span class="hljs-keyword">else</span>:
                 <span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;AI Fallback: No moves or switches available. Using Struggle/Default.&quot;</span>)
                 <span class="hljs-keyword">return</span> self.choose_default_move(battle)

    <span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">_get_llm_decision</span>(<span class="hljs-params">self, battle_state: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]:
        <span class="hljs-keyword">raise</span> NotImplementedError(<span class="hljs-string">&quot;Subclasses must implement _get_llm_decision&quot;</span>)`,wrap:!1}}),x=new K({props:{title:"🧪 TemplateAgent",local:"-templateagent",headingTag:"h2"}}),H=new IM({props:{code:"Y2xhc3MlMjBUZW1wbGF0ZUFnZW50KExMTUFnZW50QmFzZSklM0ElMEElMjAlMjAlMjAlMjAlMjIlMjIlMjIlRTQlQkQlQkYlRTclOTQlQTglRTYlQTglQTElRTYlOUQlQkZBSSUyMEFQSSVFOCVCRiU5QiVFOCVBMSU4QyVFNSU4NiVCMyVFNyVBRCU5NiVFMyU4MCU4MiUyMiUyMiUyMiUwQSUyMCUyMCUyMCUyMGRlZiUyMF9faW5pdF9fKHNlbGYlMkMlMjBhcGlfa2V5JTNBJTIwc3RyJTIwJTNEJTIwTm9uZSUyQyUyMG1vZGVsJTNBJTIwc3RyJTIwJTNEJTIwJTIybW9kZWwtbmFtZSUyMiUyQyUyMCphcmdzJTJDJTIwKiprd2FyZ3MpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwc3VwZXIoKS5fX2luaXRfXygqYXJncyUyQyUyMCoqa3dhcmdzKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHNlbGYubW9kZWwlMjAlM0QlMjBtb2RlbCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHNlbGYudGVtcGxhdGVfY2xpZW50JTIwJTNEJTIwVGVtcGxhdGVNb2RlbFByb3ZpZGVyKGFwaV9rZXklM0QuLi4pJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwc2VsZi50ZW1wbGF0ZV90b29scyUyMCUzRCUyMGxpc3Qoc2VsZi5zdGFuZGFyZF90b29scy52YWx1ZXMoKSklMEElMEElMjAlMjAlMjAlMjBhc3luYyUyMGRlZiUyMF9nZXRfbGxtX2RlY2lzaW9uKHNlbGYlMkMlMjBiYXR0bGVfc3RhdGUlM0ElMjBzdHIpJTIwLSUzRSUyMERpY3QlNUJzdHIlMkMlMjBBbnklNUQlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjIlMjIlMjJTZW5kcyUyMHN0YXRlJTIwdG8lMjB0aGUlMjBMTE0lMjBhbmQlMjBnZXRzJTIwYmFjayUyMHRoZSUyMGZ1bmN0aW9uJTIwY2FsbCUyMGRlY2lzaW9uLiUyMiUyMiUyMiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHN5c3RlbV9wcm9tcHQlMjAlM0QlMjAoJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIyWW91JTIwYXJlJTIwYSUyMC4uLiUyMiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjB1c2VyX3Byb21wdCUyMCUzRCUyMGYlMjIuLi4lMjIlMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjB0cnklM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXNwb25zZSUyMCUzRCUyMGF3YWl0JTIwc2VsZi50ZW1wbGF0ZV9jbGllbnQuY2hhdC5jb21wbGV0aW9ucy5jcmVhdGUoJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwbW9kZWwlM0RzZWxmLm1vZGVsJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwbWVzc2FnZXMlM0QlNUIlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlN0IlMjJyb2xlJTIyJTNBJTIwJTIyc3lzdGVtJTIyJTJDJTIwJTIyY29udGVudCUyMiUzQSUyMHN5c3RlbV9wcm9tcHQlN0QlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlN0IlMjJyb2xlJTIyJTNBJTIwJTIydXNlciUyMiUyQyUyMCUyMmNvbnRlbnQlMjIlM0ElMjB1c2VyX3Byb21wdCU3RCUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCU1RCUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBtZXNzYWdlJTIwJTNEJTIwcmVzcG9uc2UuY2hvaWNlcyU1QjAlNUQubWVzc2FnZSUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMCU3QiUyMmRlY2lzaW9uJTIyJTNBJTIwJTdCJTIybmFtZSUyMiUzQSUyMGZ1bmN0aW9uX25hbWUlMkMlMjAlMjJhcmd1bWVudHMlMjIlM0ElMjBhcmd1bWVudHMlN0QlN0QlMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBleGNlcHQlMjBFeGNlcHRpb24lMjBhcyUyMGUlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwcmludChmJTIyVW5leHBlY3RlZCUyMGVycm9yJTIwZHVyaW5nJTIwY2FsbCUzQSUyMCU3QmUlN0QlMjIpJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwJTdCJTIyZXJyb3IlMjIlM0ElMjBmJTIyVW5leHBlY3RlZCUyMGVycm9yJTNBJTIwJTdCZSU3RCUyMiU3RA==",highlighted:`<span class="hljs-keyword">class</span> <span class="hljs-title class_">TemplateAgent</span>(<span class="hljs-title class_ inherited__">LLMAgentBase</span>):
    <span class="hljs-string">&quot;&quot;&quot;使用模板AI API进行决策。&quot;&quot;&quot;</span>
    <span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self, api_key: <span class="hljs-built_in">str</span> = <span class="hljs-literal">None</span>, model: <span class="hljs-built_in">str</span> = <span class="hljs-string">&quot;model-name&quot;</span>, *args, **kwargs</span>):
        <span class="hljs-built_in">super</span>().__init__(*args, **kwargs)
        self.model = model
        self.template_client = TemplateModelProvider(api_key=...)
        self.template_tools = <span class="hljs-built_in">list</span>(self.standard_tools.values())

    <span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">_get_llm_decision</span>(<span class="hljs-params">self, battle_state: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]:
        <span class="hljs-string">&quot;&quot;&quot;Sends state to the LLM and gets back the function call decision.&quot;&quot;&quot;</span>
        system_prompt = (
            <span class="hljs-string">&quot;You are a ...&quot;</span>
        )
        user_prompt = <span class="hljs-string">f&quot;...&quot;</span>

        <span class="hljs-keyword">try</span>:
            response = <span class="hljs-keyword">await</span> self.template_client.chat.completions.create(
                model=self.model,
                messages=[
                    {<span class="hljs-string">&quot;role&quot;</span>: <span class="hljs-string">&quot;system&quot;</span>, <span class="hljs-string">&quot;content&quot;</span>: system_prompt},
                    {<span class="hljs-string">&quot;role&quot;</span>: <span class="hljs-string">&quot;user&quot;</span>, <span class="hljs-string">&quot;content&quot;</span>: user_prompt},
                ],
            )
            message = response.choices[<span class="hljs-number">0</span>].message

            <span class="hljs-keyword">return</span> {<span class="hljs-string">&quot;decision&quot;</span>: {<span class="hljs-string">&quot;name&quot;</span>: function_name, <span class="hljs-string">&quot;arguments&quot;</span>: arguments}}

        <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
            <span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Unexpected error during call: <span class="hljs-subst">{e}</span>&quot;</span>)
            <span class="hljs-keyword">return</span> {<span class="hljs-string">&quot;error&quot;</span>: <span class="hljs-string">f&quot;Unexpected error: <span class="hljs-subst">{e}</span>&quot;</span>}`,wrap:!1}}),D=new uM({props:{source:"https://github.com/huggingface/agents-course/blob/main/units/zh-CN/bonus-unit3/building_your_pokemon_agent.mdx"}}),{c(){C=j("meta"),Ml=t(),O=j("p"),sl=t(),y(o.$$.fragment),al=t(),y(i.$$.fragment),tl=t(),A=j("p"),A.innerHTML=Rl,nl=t(),c=j("p"),c.textContent=Xl,jl=t(),m=j("ul"),m.innerHTML=xl,el=t(),h=j("p"),h.textContent=Fl,Jl=t(),y(b.$$.fragment),yl=t(),u=j("p"),u.innerHTML=zl,Ul=t(),r=j("p"),r.innerHTML=ql,Tl=t(),d=j("p"),d.innerHTML=Hl,wl=t(),f=j("p"),f.innerHTML=Ll,pl=t(),y(_.$$.fragment),Il=t(),B=j("p"),B.innerHTML=$l,Cl=t(),Z=j("p"),Z.textContent=Pl,ol=t(),G=j("p"),G.innerHTML=Dl,il=t(),y(v.$$.fragment),Al=t(),N=j("p"),N.innerHTML=Kl,cl=t(),k=j("p"),k.innerHTML=Ol,ml=t(),E=j("ul"),E.innerHTML=lM,hl=t(),V=j("p"),V.textContent=MM,bl=t(),y(W.$$.fragment),ul=t(),g=j("ul"),g.innerHTML=sM,rl=t(),y(S.$$.fragment),dl=t(),Q=j("ul"),Q.innerHTML=aM,fl=t(),Y=j("p"),Y.textContent=tM,_l=t(),y(R.$$.fragment),Bl=t(),X=j("p"),X.innerHTML=nM,Zl=t(),y(x.$$.fragment),Gl=t(),F=j("p"),F.textContent=jM,vl=t(),z=j("p"),z.innerHTML=eM,Nl=t(),q=j("p"),q.textContent=JM,kl=t(),y(H.$$.fragment),El=t(),L=j("p"),L.textContent=yM,Vl=t(),$=j("p"),$.textContent=UM,Wl=t(),P=j("p"),P.textContent=TM,gl=t(),y(D.$$.fragment),Sl=t(),ll=j("p"),this.h()},l(l){const M=mM("svelte-u9bgzb",document.head);C=e(M,"META",{name:!0,content:!0}),M.forEach(s),Ml=n(l),O=e(l,"P",{}),wM(O).forEach(s),sl=n(l),U(o.$$.fragment,l),al=n(l),U(i.$$.fragment,l),tl=n(l),A=e(l,"P",{"data-svelte-h":!0}),J(A)!=="svelte-l0mq9j"&&(A.innerHTML=Rl),nl=n(l),c=e(l,"P",{"data-svelte-h":!0}),J(c)!=="svelte-y4aiyl"&&(c.textContent=Xl),jl=n(l),m=e(l,"UL",{"data-svelte-h":!0}),J(m)!=="svelte-1otq18s"&&(m.innerHTML=xl),el=n(l),h=e(l,"P",{"data-svelte-h":!0}),J(h)!=="svelte-1wyqkmy"&&(h.textContent=Fl),Jl=n(l),U(b.$$.fragment,l),yl=n(l),u=e(l,"P",{"data-svelte-h":!0}),J(u)!=="svelte-a0rkmd"&&(u.innerHTML=zl),Ul=n(l),r=e(l,"P",{"data-svelte-h":!0}),J(r)!=="svelte-1i87hr2"&&(r.innerHTML=ql),Tl=n(l),d=e(l,"P",{"data-svelte-h":!0}),J(d)!=="svelte-lnegje"&&(d.innerHTML=Hl),wl=n(l),f=e(l,"P",{"data-svelte-h":!0}),J(f)!=="svelte-gviwvg"&&(f.innerHTML=Ll),pl=n(l),U(_.$$.fragment,l),Il=n(l),B=e(l,"P",{"data-svelte-h":!0}),J(B)!=="svelte-15devh2"&&(B.innerHTML=$l),Cl=n(l),Z=e(l,"P",{"data-svelte-h":!0}),J(Z)!=="svelte-1eaomxa"&&(Z.textContent=Pl),ol=n(l),G=e(l,"P",{"data-svelte-h":!0}),J(G)!=="svelte-wybkpw"&&(G.innerHTML=Dl),il=n(l),U(v.$$.fragment,l),Al=n(l),N=e(l,"P",{"data-svelte-h":!0}),J(N)!=="svelte-s4mnxu"&&(N.innerHTML=Kl),cl=n(l),k=e(l,"P",{"data-svelte-h":!0}),J(k)!=="svelte-89svx0"&&(k.innerHTML=Ol),ml=n(l),E=e(l,"UL",{"data-svelte-h":!0}),J(E)!=="svelte-197aei"&&(E.innerHTML=lM),hl=n(l),V=e(l,"P",{"data-svelte-h":!0}),J(V)!=="svelte-dysi3q"&&(V.textContent=MM),bl=n(l),U(W.$$.fragment,l),ul=n(l),g=e(l,"UL",{"data-svelte-h":!0}),J(g)!=="svelte-1vu5084"&&(g.innerHTML=sM),rl=n(l),U(S.$$.fragment,l),dl=n(l),Q=e(l,"UL",{"data-svelte-h":!0}),J(Q)!=="svelte-x33l30"&&(Q.innerHTML=aM),fl=n(l),Y=e(l,"P",{"data-svelte-h":!0}),J(Y)!=="svelte-132bp0c"&&(Y.textContent=tM),_l=n(l),U(R.$$.fragment,l),Bl=n(l),X=e(l,"P",{"data-svelte-h":!0}),J(X)!=="svelte-1kzh90t"&&(X.innerHTML=nM),Zl=n(l),U(x.$$.fragment,l),Gl=n(l),F=e(l,"P",{"data-svelte-h":!0}),J(F)!=="svelte-1iw4u03"&&(F.textContent=jM),vl=n(l),z=e(l,"P",{"data-svelte-h":!0}),J(z)!=="svelte-1p73p4a"&&(z.innerHTML=eM),Nl=n(l),q=e(l,"P",{"data-svelte-h":!0}),J(q)!=="svelte-hbsb8k"&&(q.textContent=JM),kl=n(l),U(H.$$.fragment,l),El=n(l),L=e(l,"P",{"data-svelte-h":!0}),J(L)!=="svelte-5c9mfo"&&(L.textContent=yM),Vl=n(l),$=e(l,"P",{"data-svelte-h":!0}),J($)!=="svelte-1y8h4oi"&&($.textContent=UM),Wl=n(l),P=e(l,"P",{"data-svelte-h":!0}),J(P)!=="svelte-5c4fpl"&&(P.textContent=TM),gl=n(l),U(D.$$.fragment,l),Sl=n(l),ll=e(l,"P",{}),wM(ll).forEach(s),this.h()},h(){pM(C,"name","hf:doc:metadata"),pM(C,"content",dM)},m(l,M){hM(document.head,C),a(l,Ml,M),a(l,O,M),a(l,sl,M),T(o,l,M),a(l,al,M),T(i,l,M),a(l,tl,M),a(l,A,M),a(l,nl,M),a(l,c,M),a(l,jl,M),a(l,m,M),a(l,el,M),a(l,h,M),a(l,Jl,M),T(b,l,M),a(l,yl,M),a(l,u,M),a(l,Ul,M),a(l,r,M),a(l,Tl,M),a(l,d,M),a(l,wl,M),a(l,f,M),a(l,pl,M),T(_,l,M),a(l,Il,M),a(l,B,M),a(l,Cl,M),a(l,Z,M),a(l,ol,M),a(l,G,M),a(l,il,M),T(v,l,M),a(l,Al,M),a(l,N,M),a(l,cl,M),a(l,k,M),a(l,ml,M),a(l,E,M),a(l,hl,M),a(l,V,M),a(l,bl,M),T(W,l,M),a(l,ul,M),a(l,g,M),a(l,rl,M),T(S,l,M),a(l,dl,M),a(l,Q,M),a(l,fl,M),a(l,Y,M),a(l,_l,M),T(R,l,M),a(l,Bl,M),a(l,X,M),a(l,Zl,M),T(x,l,M),a(l,Gl,M),a(l,F,M),a(l,vl,M),a(l,z,M),a(l,Nl,M),a(l,q,M),a(l,kl,M),T(H,l,M),a(l,El,M),a(l,L,M),a(l,Vl,M),a(l,$,M),a(l,Wl,M),a(l,P,M),a(l,gl,M),T(D,l,M),a(l,Sl,M),a(l,ll,M),Ql=!0},p:oM,i(l){Ql||(w(o.$$.fragment,l),w(i.$$.fragment,l),w(b.$$.fragment,l),w(_.$$.fragment,l),w(v.$$.fragment,l),w(W.$$.fragment,l),w(S.$$.fragment,l),w(R.$$.fragment,l),w(x.$$.fragment,l),w(H.$$.fragment,l),w(D.$$.fragment,l),Ql=!0)},o(l){p(o.$$.fragment,l),p(i.$$.fragment,l),p(b.$$.fragment,l),p(_.$$.fragment,l),p(v.$$.fragment,l),p(W.$$.fragment,l),p(S.$$.fragment,l),p(R.$$.fragment,l),p(x.$$.fragment,l),p(H.$$.fragment,l),p(D.$$.fragment,l),Ql=!1},d(l){l&&(s(Ml),s(O),s(sl),s(al),s(tl),s(A),s(nl),s(c),s(jl),s(m),s(el),s(h),s(Jl),s(yl),s(u),s(Ul),s(r),s(Tl),s(d),s(wl),s(f),s(pl),s(Il),s(B),s(Cl),s(Z),s(ol),s(G),s(il),s(Al),s(N),s(cl),s(k),s(ml),s(E),s(hl),s(V),s(bl),s(ul),s(g),s(rl),s(dl),s(Q),s(fl),s(Y),s(_l),s(Bl),s(X),s(Zl),s(Gl),s(F),s(vl),s(z),s(Nl),s(q),s(kl),s(El),s(L),s(Vl),s($),s(Wl),s(P),s(gl),s(Sl),s(ll)),s(C),I(o,l),I(i,l),I(b,l),I(_,l),I(v,l),I(W,l),I(S,l),I(R,l),I(x,l),I(H,l),I(D,l)}}}const dM='{"title":"构建你自己的宝可梦对战智能体","local":"构建你自己的宝可梦对战智能体","sections":[{"title":"🧠 Poke-env","local":"-poke-env","sections":[],"depth":2},{"title":"⚔️ Pokémon Showdown","local":"-pokémon-showdown","sections":[],"depth":2},{"title":"🔌 LLMAgentBase","local":"-llmagentbase","sections":[{"title":"🧠 核心逻辑","local":"-核心逻辑","sections":[],"depth":3},{"title":"🔧 关键内部方法","local":"-关键内部方法","sections":[],"depth":3}],"depth":2},{"title":"🧪 TemplateAgent","local":"-templateagent","sections":[],"depth":2}],"depth":1}';function fM(Yl){return iM(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class NM extends AM{constructor(C){super(),cM(this,C,fM,rM,CM,{})}}export{NM as component};
