import{s as Cs,n as is,o as Is}from"../chunks/scheduler.505acc25.js";import{S as cs,i as ms,e,s as a,c as j,h as As,a as y,d as M,b as n,f as Ts,g as J,j as U,k as os,l as hs,m as t,n as w,t as T,o,p}from"../chunks/index.fbb49fb4.js";import{C as us}from"../chunks/CopyLLMTxtMenu.564b44fd.js";import{C as ps}from"../chunks/CodeBlock.7f0851b7.js";import{H as D}from"../chunks/Heading.511e0027.js";import{E as rs}from"../chunks/MermaidChart.svelte_svelte_type_style_lang.8c19e80e.js";function bs(Ql){let C,sl,O,Ml,i,tl,I,al,c,Vl="Now that you’ve explored the potential and limitations of Agentic AI in games, it’s time to get hands-on. In this section, you’ll <strong>build your very own AI Agent to battle in Pokémon-style turn-based combat</strong>, using everything you’ve learned throughout the course.",nl,m,xl="We’ll break the system into four key building blocks:",el,A,Rl="<li><p><strong>Poke-env:</strong> A Python library designed to train rule-based or reinforcement learning Pokémon bots.</p></li> <li><p><strong>Pokémon Showdown:</strong> An online battle simulator where your agent will fight.</p></li> <li><p><strong>LLMAgentBase:</strong> A custom Python class we’ve built to connect your LLM with the Poke-env battle environment.</p></li> <li><p><strong>TemplateAgent:</strong> A starter template you’ll complete to create your own unique battle agent.</p></li>",yl,h,zl="Let’s explore each of these components in more detail.",Ul,u,jl,r,ql='<img src="https://github.com/hsahovic/poke-env/raw/master/rl-gif.gif" alt="Battle gif"/>',Jl,b,Fl=`<a href="https://github.com/hsahovic/poke-env" rel="nofollow">Poke-env</a> is a Python interface originally built for training reinforcement learning bots by <a href="https://huggingface.co/hsahovic" rel="nofollow">Haris Sahovic</a>, but we’ve repurposed it for Agentic AI.<br/>
It allows your agent to interact with Pokémon Showdown through a simple API.`,wl,d,Hl="It provides a <code>Player</code> class from which your Agent will inherit, covering everything needed to communicate with the graphical interface.",Tl,f,Ll='<strong>Documentation</strong>: <a href="https://poke-env.readthedocs.io/en/stable/" rel="nofollow">poke-env.readthedocs.io</a><br/> <strong>Repository</strong>: <a href="https://github.com/hsahovic/poke-env" rel="nofollow">github.com/hsahovic/poke-env</a>',ol,B,pl,_,$l=`<a href="https://pokemonshowdown.com/" rel="nofollow">Pokémon Showdown</a> is an <a href="https://github.com/smogon/Pokemon-Showdown" rel="nofollow">open-source</a> battle simulator where your agent will play live Pokémon battles.<br/>
It provides a full interface to simulate and display battles in real time. In our challenge, your bot will act just like a human player, choosing moves turn by turn.`,Cl,Z,Pl="We’ve deployed a server that all participants will use to battle. Let’s see who builds the best AI battle Agent!",il,v,Kl='<strong>Repository</strong>: <a href="https://github.com/smogon/Pokemon-Showdown" rel="nofollow">github.com/smogon/Pokemon-Showdown</a><br/> <strong>Website</strong>: <a href="https://pokemonshowdown.com/" rel="nofollow">pokemonshowdown.com</a>',Il,N,cl,G,Dl=`<code>LLMAgentBase</code> is a Python class that extends the <code>Player</code> class from <strong>Poke-env</strong>.<br/>
It serves as the bridge between your <strong>LLM</strong> and the <strong>Pokémon battle simulator</strong>, handling input/output formatting and maintaining battle context.`,ml,g,Ol="This base agent provides a set of tools (defined in <code>STANDARD_TOOL_SCHEMA</code>) to interact with the environment, including:",Al,k,ls="<li><code>choose_move</code>: for selecting an attack during battle</li> <li><code>choose_switch</code>: for switching Pokémon</li>",hl,W,ss="The LLM should use these tools to make decisions during a match.",ul,Y,rl,X,Ms="<li><code>choose_move(battle: Battle)</code>: This is the main method invoked each turn. It takes a <code>Battle</code> object and returns an action string based on the LLM’s output.</li>",bl,E,dl,S,ts="<li><p><code>_format_battle_state(battle)</code>: Converts the current battle state into a string, making it suitable for sending to the LLM.</p></li> <li><p><code>_find_move_by_name(battle, move_name)</code>: Finds a move by name, used in LLM responses that call <code>choose_move</code>.</p></li> <li><p><code>_find_pokemon_by_name(battle, pokemon_name)</code>: Locates a specific Pokémon to switch into, based on the LLM’s switch command.</p></li> <li><p><code>_get_llm_decision(battle_state)</code>: This method is abstract in the base class. You’ll need to implement it in your own agent (see next section), where you define how to query the LLM and parse its response.</p></li>",fl,Q,as="Here’s an excerpt showing how that decision-making works:",Bl,V,_l,x,ns='<strong>Full source code</strong>: <a href="https://huggingface.co/spaces/Jofthomas/twitch_streaming/blob/main/agents.py" rel="nofollow">agents.py</a>',Zl,R,vl,z,es="Now comes the fun part! With LLMAgentBase as your foundation, it’s time to implement your own agent, with your own strategy to climb the leaderboard.",Nl,q,ys='You’ll start from this template and build your own logic. We’ve also provided three <a href="https://huggingface.co/spaces/Jofthomas/twitch_streaming/blob/main/agents.py" rel="nofollow">complete examples</a> using <strong>OpenAI</strong>, <strong>Mistral</strong>, and <strong>Gemini</strong> models to guide you.',Gl,F,Us="Here’s a simplified version of the template:",gl,H,kl,L,js="This code won’t run out of the box, it’s a blueprint for your custom logic.",Wl,$,Js="With all the pieces ready, it’s your turn to build a competitive agent. In the next section, we’ll show how to deploy your agent to our server and battle others in real-time.",Yl,P,ws="Let the battle begin! 🔥",Xl,K,El,ll,Sl;return i=new us({props:{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"}}),I=new D({props:{title:"Build Your Own Pokémon Battle Agent",local:"build-your-own-pokémon-battle-agent",headingTag:"h1"}}),u=new D({props:{title:"🧠 Poke-env",local:"-poke-env",headingTag:"h2"}}),B=new D({props:{title:"⚔️ Pokémon Showdown",local:"-pokémon-showdown",headingTag:"h2"}}),N=new D({props:{title:"🔌 LLMAgentBase",local:"-llmagentbase",headingTag:"h2"}}),Y=new D({props:{title:"🧠 Core Logic",local:"-core-logic",headingTag:"h3"}}),E=new D({props:{title:"🔧 Key Internal Methods",local:"-key-internal-methods",headingTag:"h3"}}),V=new ps({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"># Prioritize exact ID match</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"># Fallback: Check display name (less reliable)</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"># Normalize the species name for comparison</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}}),R=new D({props:{title:"🧪 TemplateAgent",local:"-templateagent",headingTag:"h2"}}),H=new ps({props:{code:"Y2xhc3MlMjBUZW1wbGF0ZUFnZW50KExMTUFnZW50QmFzZSklM0ElMEElMjAlMjAlMjAlMjAlMjIlMjIlMjJVc2VzJTIwVGVtcGxhdGUlMjBBSSUyMEFQSSUyMGZvciUyMGRlY2lzaW9ucy4lMjIlMjIlMjIlMEElMjAlMjAlMjAlMjBkZWYlMjBfX2luaXRfXyhzZWxmJTJDJTIwYXBpX2tleSUzQSUyMHN0ciUyMCUzRCUyME5vbmUlMkMlMjBtb2RlbCUzQSUyMHN0ciUyMCUzRCUyMCUyMm1vZGVsLW5hbWUlMjIlMkMlMjAqYXJncyUyQyUyMCoqa3dhcmdzKSUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHN1cGVyKCkuX19pbml0X18oKmFyZ3MlMkMlMjAqKmt3YXJncyklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBzZWxmLm1vZGVsJTIwJTNEJTIwbW9kZWwlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBzZWxmLnRlbXBsYXRlX2NsaWVudCUyMCUzRCUyMFRlbXBsYXRlTW9kZWxQcm92aWRlcihhcGlfa2V5JTNELi4uKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHNlbGYudGVtcGxhdGVfdG9vbHMlMjAlM0QlMjBsaXN0KHNlbGYuc3RhbmRhcmRfdG9vbHMudmFsdWVzKCkpJTBBJTBBJTIwJTIwJTIwJTIwYXN5bmMlMjBkZWYlMjBfZ2V0X2xsbV9kZWNpc2lvbihzZWxmJTJDJTIwYmF0dGxlX3N0YXRlJTNBJTIwc3RyKSUyMC0lM0UlMjBEaWN0JTVCc3RyJTJDJTIwQW55JTVEJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIyJTIyJTIyU2VuZHMlMjBzdGF0ZSUyMHRvJTIwdGhlJTIwTExNJTIwYW5kJTIwZ2V0cyUyMGJhY2slMjB0aGUlMjBmdW5jdGlvbiUyMGNhbGwlMjBkZWNpc2lvbi4lMjIlMjIlMjIlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBzeXN0ZW1fcHJvbXB0JTIwJTNEJTIwKCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMllvdSUyMGFyZSUyMGElMjAuLi4lMjIlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjApJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwdXNlcl9wcm9tcHQlMjAlM0QlMjBmJTIyLi4uJTIyJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwdHJ5JTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmVzcG9uc2UlMjAlM0QlMjBhd2FpdCUyMHNlbGYudGVtcGxhdGVfY2xpZW50LmNoYXQuY29tcGxldGlvbnMuY3JlYXRlKCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG1vZGVsJTNEc2VsZi5tb2RlbCUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG1lc3NhZ2VzJTNEJTVCJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTdCJTIycm9sZSUyMiUzQSUyMCUyMnN5c3RlbSUyMiUyQyUyMCUyMmNvbnRlbnQlMjIlM0ElMjBzeXN0ZW1fcHJvbXB0JTdEJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTdCJTIycm9sZSUyMiUzQSUyMCUyMnVzZXIlMjIlMkMlMjAlMjJjb250ZW50JTIyJTNBJTIwdXNlcl9wcm9tcHQlN0QlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlNUQlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjApJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwbWVzc2FnZSUyMCUzRCUyMHJlc3BvbnNlLmNob2ljZXMlNUIwJTVELm1lc3NhZ2UlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjAlN0IlMjJkZWNpc2lvbiUyMiUzQSUyMCU3QiUyMm5hbWUlMjIlM0ElMjBmdW5jdGlvbl9uYW1lJTJDJTIwJTIyYXJndW1lbnRzJTIyJTNBJTIwYXJndW1lbnRzJTdEJTdEJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwZXhjZXB0JTIwRXhjZXB0aW9uJTIwYXMlMjBlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcHJpbnQoZiUyMlVuZXhwZWN0ZWQlMjBlcnJvciUyMGR1cmluZyUyMGNhbGwlM0ElMjAlN0JlJTdEJTIyKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMCU3QiUyMmVycm9yJTIyJTNBJTIwZiUyMlVuZXhwZWN0ZWQlMjBlcnJvciUzQSUyMCU3QmUlN0QlMjIlN0Q=",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;Uses Template AI API for decisions.&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}}),K=new rs({props:{source:"https://github.com/huggingface/agents-course/blob/main/units/en/bonus-unit3/building_your_pokemon_agent.mdx"}}),{c(){C=e("meta"),sl=a(),O=e("p"),Ml=a(),j(i.$$.fragment),tl=a(),j(I.$$.fragment),al=a(),c=e("p"),c.innerHTML=Vl,nl=a(),m=e("p"),m.textContent=xl,el=a(),A=e("ul"),A.innerHTML=Rl,yl=a(),h=e("p"),h.textContent=zl,Ul=a(),j(u.$$.fragment),jl=a(),r=e("p"),r.innerHTML=ql,Jl=a(),b=e("p"),b.innerHTML=Fl,wl=a(),d=e("p"),d.innerHTML=Hl,Tl=a(),f=e("p"),f.innerHTML=Ll,ol=a(),j(B.$$.fragment),pl=a(),_=e("p"),_.innerHTML=$l,Cl=a(),Z=e("p"),Z.textContent=Pl,il=a(),v=e("p"),v.innerHTML=Kl,Il=a(),j(N.$$.fragment),cl=a(),G=e("p"),G.innerHTML=Dl,ml=a(),g=e("p"),g.innerHTML=Ol,Al=a(),k=e("ul"),k.innerHTML=ls,hl=a(),W=e("p"),W.textContent=ss,ul=a(),j(Y.$$.fragment),rl=a(),X=e("ul"),X.innerHTML=Ms,bl=a(),j(E.$$.fragment),dl=a(),S=e("ul"),S.innerHTML=ts,fl=a(),Q=e("p"),Q.textContent=as,Bl=a(),j(V.$$.fragment),_l=a(),x=e("p"),x.innerHTML=ns,Zl=a(),j(R.$$.fragment),vl=a(),z=e("p"),z.textContent=es,Nl=a(),q=e("p"),q.innerHTML=ys,Gl=a(),F=e("p"),F.textContent=Us,gl=a(),j(H.$$.fragment),kl=a(),L=e("p"),L.textContent=js,Wl=a(),$=e("p"),$.textContent=Js,Yl=a(),P=e("p"),P.textContent=ws,Xl=a(),j(K.$$.fragment),El=a(),ll=e("p"),this.h()},l(l){const s=As("svelte-u9bgzb",document.head);C=y(s,"META",{name:!0,content:!0}),s.forEach(M),sl=n(l),O=y(l,"P",{}),Ts(O).forEach(M),Ml=n(l),J(i.$$.fragment,l),tl=n(l),J(I.$$.fragment,l),al=n(l),c=y(l,"P",{"data-svelte-h":!0}),U(c)!=="svelte-15onf7o"&&(c.innerHTML=Vl),nl=n(l),m=y(l,"P",{"data-svelte-h":!0}),U(m)!=="svelte-80pqn7"&&(m.textContent=xl),el=n(l),A=y(l,"UL",{"data-svelte-h":!0}),U(A)!=="svelte-12bbsbs"&&(A.innerHTML=Rl),yl=n(l),h=y(l,"P",{"data-svelte-h":!0}),U(h)!=="svelte-14tx904"&&(h.textContent=zl),Ul=n(l),J(u.$$.fragment,l),jl=n(l),r=y(l,"P",{"data-svelte-h":!0}),U(r)!=="svelte-a0rkmd"&&(r.innerHTML=ql),Jl=n(l),b=y(l,"P",{"data-svelte-h":!0}),U(b)!=="svelte-6k4kyn"&&(b.innerHTML=Fl),wl=n(l),d=y(l,"P",{"data-svelte-h":!0}),U(d)!=="svelte-vsvnc8"&&(d.innerHTML=Hl),Tl=n(l),f=y(l,"P",{"data-svelte-h":!0}),U(f)!=="svelte-1tn5h7d"&&(f.innerHTML=Ll),ol=n(l),J(B.$$.fragment,l),pl=n(l),_=y(l,"P",{"data-svelte-h":!0}),U(_)!=="svelte-16cq85o"&&(_.innerHTML=$l),Cl=n(l),Z=y(l,"P",{"data-svelte-h":!0}),U(Z)!=="svelte-q73emc"&&(Z.textContent=Pl),il=n(l),v=y(l,"P",{"data-svelte-h":!0}),U(v)!=="svelte-kkgamm"&&(v.innerHTML=Kl),Il=n(l),J(N.$$.fragment,l),cl=n(l),G=y(l,"P",{"data-svelte-h":!0}),U(G)!=="svelte-1jjw3w5"&&(G.innerHTML=Dl),ml=n(l),g=y(l,"P",{"data-svelte-h":!0}),U(g)!=="svelte-j0gif1"&&(g.innerHTML=Ol),Al=n(l),k=y(l,"UL",{"data-svelte-h":!0}),U(k)!=="svelte-zzfwig"&&(k.innerHTML=ls),hl=n(l),W=y(l,"P",{"data-svelte-h":!0}),U(W)!=="svelte-tti1gv"&&(W.textContent=ss),ul=n(l),J(Y.$$.fragment,l),rl=n(l),X=y(l,"UL",{"data-svelte-h":!0}),U(X)!=="svelte-1hun6po"&&(X.innerHTML=Ms),bl=n(l),J(E.$$.fragment,l),dl=n(l),S=y(l,"UL",{"data-svelte-h":!0}),U(S)!=="svelte-cgbcxh"&&(S.innerHTML=ts),fl=n(l),Q=y(l,"P",{"data-svelte-h":!0}),U(Q)!=="svelte-s452ne"&&(Q.textContent=as),Bl=n(l),J(V.$$.fragment,l),_l=n(l),x=y(l,"P",{"data-svelte-h":!0}),U(x)!=="svelte-1opxous"&&(x.innerHTML=ns),Zl=n(l),J(R.$$.fragment,l),vl=n(l),z=y(l,"P",{"data-svelte-h":!0}),U(z)!=="svelte-1d3y92c"&&(z.textContent=es),Nl=n(l),q=y(l,"P",{"data-svelte-h":!0}),U(q)!=="svelte-1gx2s0i"&&(q.innerHTML=ys),Gl=n(l),F=y(l,"P",{"data-svelte-h":!0}),U(F)!=="svelte-g3yucj"&&(F.textContent=Us),gl=n(l),J(H.$$.fragment,l),kl=n(l),L=y(l,"P",{"data-svelte-h":!0}),U(L)!=="svelte-oim3xo"&&(L.textContent=js),Wl=n(l),$=y(l,"P",{"data-svelte-h":!0}),U($)!=="svelte-1qifh46"&&($.textContent=Js),Yl=n(l),P=y(l,"P",{"data-svelte-h":!0}),U(P)!=="svelte-frbzfm"&&(P.textContent=ws),Xl=n(l),J(K.$$.fragment,l),El=n(l),ll=y(l,"P",{}),Ts(ll).forEach(M),this.h()},h(){os(C,"name","hf:doc:metadata"),os(C,"content",ds)},m(l,s){hs(document.head,C),t(l,sl,s),t(l,O,s),t(l,Ml,s),w(i,l,s),t(l,tl,s),w(I,l,s),t(l,al,s),t(l,c,s),t(l,nl,s),t(l,m,s),t(l,el,s),t(l,A,s),t(l,yl,s),t(l,h,s),t(l,Ul,s),w(u,l,s),t(l,jl,s),t(l,r,s),t(l,Jl,s),t(l,b,s),t(l,wl,s),t(l,d,s),t(l,Tl,s),t(l,f,s),t(l,ol,s),w(B,l,s),t(l,pl,s),t(l,_,s),t(l,Cl,s),t(l,Z,s),t(l,il,s),t(l,v,s),t(l,Il,s),w(N,l,s),t(l,cl,s),t(l,G,s),t(l,ml,s),t(l,g,s),t(l,Al,s),t(l,k,s),t(l,hl,s),t(l,W,s),t(l,ul,s),w(Y,l,s),t(l,rl,s),t(l,X,s),t(l,bl,s),w(E,l,s),t(l,dl,s),t(l,S,s),t(l,fl,s),t(l,Q,s),t(l,Bl,s),w(V,l,s),t(l,_l,s),t(l,x,s),t(l,Zl,s),w(R,l,s),t(l,vl,s),t(l,z,s),t(l,Nl,s),t(l,q,s),t(l,Gl,s),t(l,F,s),t(l,gl,s),w(H,l,s),t(l,kl,s),t(l,L,s),t(l,Wl,s),t(l,$,s),t(l,Yl,s),t(l,P,s),t(l,Xl,s),w(K,l,s),t(l,El,s),t(l,ll,s),Sl=!0},p:is,i(l){Sl||(T(i.$$.fragment,l),T(I.$$.fragment,l),T(u.$$.fragment,l),T(B.$$.fragment,l),T(N.$$.fragment,l),T(Y.$$.fragment,l),T(E.$$.fragment,l),T(V.$$.fragment,l),T(R.$$.fragment,l),T(H.$$.fragment,l),T(K.$$.fragment,l),Sl=!0)},o(l){o(i.$$.fragment,l),o(I.$$.fragment,l),o(u.$$.fragment,l),o(B.$$.fragment,l),o(N.$$.fragment,l),o(Y.$$.fragment,l),o(E.$$.fragment,l),o(V.$$.fragment,l),o(R.$$.fragment,l),o(H.$$.fragment,l),o(K.$$.fragment,l),Sl=!1},d(l){l&&(M(sl),M(O),M(Ml),M(tl),M(al),M(c),M(nl),M(m),M(el),M(A),M(yl),M(h),M(Ul),M(jl),M(r),M(Jl),M(b),M(wl),M(d),M(Tl),M(f),M(ol),M(pl),M(_),M(Cl),M(Z),M(il),M(v),M(Il),M(cl),M(G),M(ml),M(g),M(Al),M(k),M(hl),M(W),M(ul),M(rl),M(X),M(bl),M(dl),M(S),M(fl),M(Q),M(Bl),M(_l),M(x),M(Zl),M(vl),M(z),M(Nl),M(q),M(Gl),M(F),M(gl),M(kl),M(L),M(Wl),M($),M(Yl),M(P),M(Xl),M(El),M(ll)),M(C),p(i,l),p(I,l),p(u,l),p(B,l),p(N,l),p(Y,l),p(E,l),p(V,l),p(R,l),p(H,l),p(K,l)}}}const ds='{"title":"Build Your Own Pokémon Battle Agent","local":"build-your-own-pokémon-battle-agent","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":"🧠 Core Logic","local":"-core-logic","sections":[],"depth":3},{"title":"🔧 Key Internal Methods","local":"-key-internal-methods","sections":[],"depth":3}],"depth":2},{"title":"🧪 TemplateAgent","local":"-templateagent","sections":[],"depth":2}],"depth":1}';function fs(Ql){return Is(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class gs extends cs{constructor(C){super(),ms(this,C,fs,bs,Cs,{})}}export{gs as component};
