import{s as is,n as Is,o as Cs}from"../chunks/scheduler.505acc25.js";import{S as cs,i as ms,e as t,s as n,c as j,h as As,a as y,d as M,b as e,f as ws,g as U,j as J,k as os,l as rs,m as a,n as T,t as w,o,p}from"../chunks/index.fbb49fb4.js";import{C as us}from"../chunks/CopyLLMTxtMenu.38c593c4.js";import{C as ps}from"../chunks/CodeBlock.2ead06c8.js";import{H as K}from"../chunks/Heading.511e0027.js";import{E as bs}from"../chunks/MermaidChart.svelte_svelte_type_style_lang.9ca82795.js";function ds(Vl){let i,sl,O,Ml,I,al,C,nl,c,Rl="Ahora que has explorado el potencial y las limitaciones de la IA Agéntica en los juegos, es hora de poner manos a la obra. En esta sección, <strong>construirás tu propio Agente de IA para luchar en combates por turnos al estilo Pokémon</strong>, utilizando todo lo que has aprendido a lo largo del curso.",el,m,Xl="Dividiremos el sistema en cuatro bloques de construcción clave:",tl,A,zl="<li><p><strong>Poke-env:</strong> Una biblioteca de Python diseñada para entrenar bots de Pokémon basados en reglas o aprendizaje por refuerzo.</p></li> <li><p><strong>Pokémon Showdown:</strong> Un simulador de batallas en línea donde luchará tu agente.</p></li> <li><p><strong>LLMAgentBase:</strong> Una clase personalizada de Python que hemos construido para conectar tu LLM con el entorno de batalla de Poke-env.</p></li> <li><p><strong>TemplateAgent:</strong> Una plantilla de inicio que completarás para crear tu propio agente de batalla único.</p></li>",yl,r,xl="Exploremos cada uno de estos componentes con más detalle.",Jl,u,jl,b,ql='<img src="https://github.com/hsahovic/poke-env/raw/master/rl-gif.gif" alt="Gif de batalla"/>',Ul,d,Fl=`<a href="https://github.com/hsahovic/poke-env" rel="nofollow">Poke-env</a> es una interfaz de Python construida originalmente para entrenar bots de aprendizaje por refuerzo por <a href="https://huggingface.co/hsahovic" rel="nofollow">Haris Sahovic</a>, pero la hemos adaptado para la IA Agéntica.
Permite que tu agente interactúe con Pokémon Showdown a través de una API simple.`,Tl,h,Hl="Proporciona una clase <code>Player</code> de la cual tu Agente heredará, cubriendo todo lo necesario para comunicarse con la interfaz gráfica.",wl,B,Ll='<strong>Documentación</strong>: <a href="https://poke-env.readthedocs.io/en/stable/" rel="nofollow">poke-env.readthedocs.io</a> <strong>Repositorio</strong>: <a href="https://github.com/hsahovic/poke-env" rel="nofollow">github.com/hsahovic/poke-env</a>',ol,f,pl,Z,$l=`<a href="https://pokemonshowdown.com/" rel="nofollow">Pokémon Showdown</a> es un simulador de batallas <a href="https://github.com/smogon/Pokemon-Showdown" rel="nofollow">de código abierto</a> donde tu agente jugará batallas Pokémon en vivo.
Proporciona una interfaz completa para simular y mostrar batallas en tiempo real. En nuestro desafío, tu bot actuará como un jugador humano, eligiendo movimientos turno por turno.`,il,_,Pl="Hemos desplegado un servidor que todos los participantes usarán para luchar. ¡Veamos quién construye el mejor Agente de batalla de IA!",Il,v,Dl='<strong>Repositorio</strong>: <a href="https://github.com/smogon/Pokemon-Showdown" rel="nofollow">github.com/smogon/Pokemon-Showdown</a> <strong>Sitio web</strong>: <a href="https://pokemonshowdown.com/" rel="nofollow">pokemonshowdown.com</a>',Cl,G,cl,k,Kl=`<code>LLMAgentBase</code> es una clase de Python que extiende la clase <code>Player</code> de <strong>Poke-env</strong>.
Sirve como puente entre tu <strong>LLM</strong> y el <strong>simulador de batallas Pokémon</strong>, manejando el formato de entrada/salida y manteniendo el contexto de la batalla.`,ml,W,Ol="Este agente base proporciona un conjunto de herramientas (definidas en <code>STANDARD_TOOL_SCHEMA</code>) para interactuar con el entorno, incluyendo:",Al,E,ls="<li><code>choose_move</code>: para seleccionar un ataque durante la batalla</li> <li><code>choose_switch</code>: para cambiar de Pokémon</li>",rl,N,ss="El LLM debe usar estas herramientas para tomar decisiones durante una partida.",ul,g,bl,Y,Ms="<li><code>choose_move(battle: Battle)</code>: Este es el método principal invocado en cada turno. Toma un objeto <code>Battle</code> y devuelve una cadena de acción basada en la salida del LLM.</li>",dl,S,hl,Q,as="<li><p><code>_format_battle_state(battle)</code>: Convierte el estado actual de la batalla en una cadena, haciéndolo adecuado para enviarlo al LLM.</p></li> <li><p><code>_find_move_by_name(battle, move_name)</code>: Encuentra un movimiento por nombre, utilizado en las respuestas del LLM que llaman a <code>choose_move</code>.</p></li> <li><p><code>_find_pokemon_by_name(battle, pokemon_name)</code>: Localiza un Pokémon específico para cambiar, basado en el comando de cambio del LLM.</p></li> <li><p><code>_get_llm_decision(battle_state)</code>: Este método es abstracto en la clase base. Deberás implementarlo en tu propio agente (ver sección siguiente), donde defines cómo consultar al LLM y analizar su respuesta.</p></li>",Bl,V,ns="Aquí hay un extracto que muestra cómo funciona esa toma de decisiones:",fl,R,Zl,X,es='<strong>Código fuente completo</strong>: <a href="https://huggingface.co/spaces/Jofthomas/twitch_streaming/blob/main/agents.py" rel="nofollow">agents.py</a>',_l,z,vl,x,ts="¡Ahora viene la parte divertida! Con LLMAgentBase como tu base, es hora de implementar tu propio agente, con tu propia estrategia para escalar en la tabla de clasificación.",Gl,q,ys='Comenzarás desde esta plantilla y construirás tu propia lógica. También hemos proporcionado tres <a href="https://huggingface.co/spaces/Jofthomas/twitch_streaming/blob/main/agents.py" rel="nofollow">ejemplos completos</a> usando los modelos <strong>OpenAI</strong>, <strong>Mistral</strong> y <strong>Gemini</strong> para guiarte.',kl,F,Js="Aquí tienes una versión simplificada de la plantilla:",Wl,H,El,L,js="Este código no se ejecutará tal cual, es un plano para tu lógica personalizada.",Nl,$,Us="Con todas las piezas listas, es tu turno de construir un agente competitivo. En la próxima sección, mostraremos cómo desplegar tu agente en nuestro servidor y luchar contra otros en tiempo real.",gl,P,Ts="¡Que comience la batalla! 🔥",Yl,D,Sl,ll,Ql;return I=new us({props:{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"}}),C=new K({props:{title:"Construye tu Propio Agente de Batalla Pokémon",local:"construye-tu-propio-agente-de-batalla-pokémon",headingTag:"h1"}}),u=new K({props:{title:"🧠 Poke-env",local:"-poke-env",headingTag:"h2"}}),f=new K({props:{title:"⚔️ Pokémon Showdown",local:"-pokémon-showdown",headingTag:"h2"}}),G=new K({props:{title:"🔌 LLMAgentBase",local:"-llmagentbase",headingTag:"h2"}}),g=new K({props:{title:"🧠 Lógica Central",local:"-lógica-central",headingTag:"h3"}}),S=new K({props:{title:"🔧 Métodos Internos Clave",local:"-métodos-internos-clave",headingTag:"h3"}}),R=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;Tu Pokémon activo: <span class="hljs-subst">{active_pkmn.species}</span> &quot;</span> \\
                           <span class="hljs-string">f&quot;(Tipo: <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;Estado: <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;Ninguno&#x27;</span>}</span> &quot;</span> \\
                           <span class="hljs-string">f&quot;Mejoras: <span class="hljs-subst">{active_pkmn.boosts}</span>&quot;</span>

        opponent_pkmn = battle.opponent_active_pokemon
        opp_info_str = <span class="hljs-string">&quot;Desconocido&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;(Tipo: <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;Estado: <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;Ninguno&#x27;</span>}</span> &quot;</span> \\
                           <span class="hljs-string">f&quot;Mejoras: <span class="hljs-subst">{opponent_pkmn.boosts}</span>&quot;</span>
        opponent_pkmn_info = <span class="hljs-string">f&quot;El Pokémon activo del oponente: <span class="hljs-subst">{opp_info_str}</span>&quot;</span>

        available_moves_info = <span class="hljs-string">&quot;Movimientos disponibles:\\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> (Tipo: <span class="hljs-subst">{move.<span class="hljs-built_in">type</span>}</span>, BP: <span class="hljs-subst">{move.base_power}</span>, Precisión: <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;- Ninguno (Debes cambiar o luchar con Struggle)&quot;</span>

        available_switches_info = <span class="hljs-string">&quot;Cambios disponibles:\\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>%, Estado: <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;Ninguno&#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;- Ninguno&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;Clima: <span class="hljs-subst">{battle.weather}</span>\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;Terrenos: <span class="hljs-subst">{battle.fields}</span>\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;Condiciones de tu lado: <span class="hljs-subst">{battle.side_conditions}</span>\\n&quot;</span> \\
                    <span class="hljs-string">f&quot;Condiciones del lado del oponente: <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"># Prioriza la coincidencia exacta de 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"># Fallback: Verifica el nombre de visualización (menos confiable)</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;Advertencia: Coincidencia de movimiento por nombre de visualización &#x27;<span class="hljs-subst">{move.name}</span>&#x27; en lugar de ID &#x27;<span class="hljs-subst">{move.<span class="hljs-built_in">id</span>}</span>&#x27;. Entrada fue &#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"># Normaliza el nombre de la especie para comparación</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;Decisión de la IA: Usando movimiento &#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;La IA eligió un movimiento no disponible/no válido &#x27;<span class="hljs-subst">{move_name}</span>&#x27;.&quot;</span>
                <span class="hljs-keyword">else</span>:
                     fallback_reason = <span class="hljs-string">&quot;La IA llamó a &#x27;choose_move&#x27; sin &#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;Decisión de la IA: Cambiando a &#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;La IA eligió un cambio no disponible/no válido &#x27;<span class="hljs-subst">{pokemon_name}</span>&#x27;.&quot;</span>
                <span class="hljs-keyword">else</span>:
                    fallback_reason = <span class="hljs-string">&quot;La IA llamó a &#x27;choose_switch&#x27; sin &#x27;pokemon_name&#x27;.&quot;</span>
            <span class="hljs-keyword">else</span>:
                fallback_reason = <span class="hljs-string">f&quot;La IA llamó a una función desconocida &#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;Error de la API: <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;La IA no proporcionó una llamada de función válida.&quot;</span>
                 <span class="hljs-keyword">else</span>:
                      fallback_reason = <span class="hljs-string">&quot;Error desconocido al procesar la decisión de la IA.&quot;</span>

            <span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Advertencia: <span class="hljs-subst">{fallback_reason}</span> Seleccionando acción aleatoria.&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;Fallback de la IA: No hay movimientos ni cambios disponibles. Usando 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;Las subclases deben implementar _get_llm_decision&quot;</span>)`,wrap:!1}}),z=new K({props:{title:"🧪 Plantilla de Agente",local:"-plantilla-de-agente",headingTag:"h2"}}),H=new ps({props:{code:"Y2xhc3MlMjBUZW1wbGF0ZUFnZW50KExMTUFnZW50QmFzZSklM0ElMEElMjAlMjAlMjAlMjAlMjIlMjIlMjJVdGlsaXphJTIwbGElMjBBUEklMjBkZSUyMFRlbXBsYXRlJTIwQUklMjBwYXJhJTIwdG9tYXIlMjBkZWNpc2lvbmVzLiUyMiUyMiUyMiUwQSUyMCUyMCUyMCUyMGRlZiUyMF9faW5pdF9fKHNlbGYlMkMlMjBhcGlfa2V5JTNBJTIwc3RyJTIwJTNEJTIwTm9uZSUyQyUyMG1vZGVsJTNBJTIwc3RyJTIwJTNEJTIwJTIybW9kZWwtbmFtZSUyMiUyQyUyMCphcmdzJTJDJTIwKiprd2FyZ3MpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwc3VwZXIoKS5fX2luaXRfXygqYXJncyUyQyUyMCoqa3dhcmdzKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHNlbGYubW9kZWwlMjAlM0QlMjBtb2RlbCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHNlbGYudGVtcGxhdGVfY2xpZW50JTIwJTNEJTIwVGVtcGxhdGVNb2RlbFByb3ZpZGVyKGFwaV9rZXklM0QuLi4pJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwc2VsZi50ZW1wbGF0ZV90b29scyUyMCUzRCUyMGxpc3Qoc2VsZi5zdGFuZGFyZF90b29scy52YWx1ZXMoKSklMEElMEElMjAlMjAlMjAlMjBhc3luYyUyMGRlZiUyMF9nZXRfbGxtX2RlY2lzaW9uKHNlbGYlMkMlMjBiYXR0bGVfc3RhdGUlM0ElMjBzdHIpJTIwLSUzRSUyMERpY3QlNUJzdHIlMkMlMjBBbnklNUQlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjIlMjIlMjJFbnYlQzMlQURhJTIwZWwlMjBlc3RhZG8lMjBhbCUyMExMTSUyMHklMjBvYnRpZW5lJTIwbGElMjBkZWNpc2klQzMlQjNuJTIwZGUlMjBsbGFtYWRhJTIwZGUlMjBmdW5jaSVDMyVCM24uJTIyJTIyJTIyJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwc3lzdGVtX3Byb21wdCUyMCUzRCUyMCglMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJFcmVzJTIwdW4lMjAuLi4lMjIlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjApJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwdXNlcl9wcm9tcHQlMjAlM0QlMjBmJTIyLi4uJTIyJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwdHJ5JTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmVzcG9uc2UlMjAlM0QlMjBhd2FpdCUyMHNlbGYudGVtcGxhdGVfY2xpZW50LmNoYXQuY29tcGxldGlvbnMuY3JlYXRlKCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG1vZGVsJTNEc2VsZi5tb2RlbCUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG1lc3NhZ2VzJTNEJTVCJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTdCJTIycm9sZSUyMiUzQSUyMCUyMnN5c3RlbSUyMiUyQyUyMCUyMmNvbnRlbnQlMjIlM0ElMjBzeXN0ZW1fcHJvbXB0JTdEJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTdCJTIycm9sZSUyMiUzQSUyMCUyMnVzZXIlMjIlMkMlMjAlMjJjb250ZW50JTIyJTNBJTIwdXNlcl9wcm9tcHQlN0QlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlNUQlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjApJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwbWVzc2FnZSUyMCUzRCUyMHJlc3BvbnNlLmNob2ljZXMlNUIwJTVELm1lc3NhZ2UlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjAlN0IlMjJkZWNpc2lvbiUyMiUzQSUyMCU3QiUyMm5hbWUlMjIlM0ElMjBmdW5jdGlvbl9uYW1lJTJDJTIwJTIyYXJndW1lbnRzJTIyJTNBJTIwYXJndW1lbnRzJTdEJTdEJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwZXhjZXB0JTIwRXhjZXB0aW9uJTIwYXMlMjBlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcHJpbnQoZiUyMkVycm9yJTIwaW5lc3BlcmFkbyUyMGR1cmFudGUlMjBsYSUyMGxsYW1hZGElM0ElMjAlN0JlJTdEJTIyKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMCU3QiUyMmVycm9yJTIyJTNBJTIwZiUyMkVycm9yJTIwaW5lc3BlcmFkbyUzQSUyMCU3QmUlN0QlMjIlN0Q=",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;Utiliza la API de Template AI para tomar decisiones.&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;Envía el estado al LLM y obtiene la decisión de llamada de función.&quot;&quot;&quot;</span>
        system_prompt = (
            <span class="hljs-string">&quot;Eres un ...&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;Error inesperado durante la llamada: <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;Error inesperado: <span class="hljs-subst">{e}</span>&quot;</span>}`,wrap:!1}}),D=new bs({props:{source:"https://github.com/huggingface/agents-course/blob/main/units/es/bonus-unit3/building_your_pokemon_agent.mdx"}}),{c(){i=t("meta"),sl=n(),O=t("p"),Ml=n(),j(I.$$.fragment),al=n(),j(C.$$.fragment),nl=n(),c=t("p"),c.innerHTML=Rl,el=n(),m=t("p"),m.textContent=Xl,tl=n(),A=t("ul"),A.innerHTML=zl,yl=n(),r=t("p"),r.textContent=xl,Jl=n(),j(u.$$.fragment),jl=n(),b=t("p"),b.innerHTML=ql,Ul=n(),d=t("p"),d.innerHTML=Fl,Tl=n(),h=t("p"),h.innerHTML=Hl,wl=n(),B=t("p"),B.innerHTML=Ll,ol=n(),j(f.$$.fragment),pl=n(),Z=t("p"),Z.innerHTML=$l,il=n(),_=t("p"),_.textContent=Pl,Il=n(),v=t("p"),v.innerHTML=Dl,Cl=n(),j(G.$$.fragment),cl=n(),k=t("p"),k.innerHTML=Kl,ml=n(),W=t("p"),W.innerHTML=Ol,Al=n(),E=t("ul"),E.innerHTML=ls,rl=n(),N=t("p"),N.textContent=ss,ul=n(),j(g.$$.fragment),bl=n(),Y=t("ul"),Y.innerHTML=Ms,dl=n(),j(S.$$.fragment),hl=n(),Q=t("ul"),Q.innerHTML=as,Bl=n(),V=t("p"),V.textContent=ns,fl=n(),j(R.$$.fragment),Zl=n(),X=t("p"),X.innerHTML=es,_l=n(),j(z.$$.fragment),vl=n(),x=t("p"),x.textContent=ts,Gl=n(),q=t("p"),q.innerHTML=ys,kl=n(),F=t("p"),F.textContent=Js,Wl=n(),j(H.$$.fragment),El=n(),L=t("p"),L.textContent=js,Nl=n(),$=t("p"),$.textContent=Us,gl=n(),P=t("p"),P.textContent=Ts,Yl=n(),j(D.$$.fragment),Sl=n(),ll=t("p"),this.h()},l(l){const s=As("svelte-u9bgzb",document.head);i=y(s,"META",{name:!0,content:!0}),s.forEach(M),sl=e(l),O=y(l,"P",{}),ws(O).forEach(M),Ml=e(l),U(I.$$.fragment,l),al=e(l),U(C.$$.fragment,l),nl=e(l),c=y(l,"P",{"data-svelte-h":!0}),J(c)!=="svelte-k0s4e1"&&(c.innerHTML=Rl),el=e(l),m=y(l,"P",{"data-svelte-h":!0}),J(m)!=="svelte-10oxgqi"&&(m.textContent=Xl),tl=e(l),A=y(l,"UL",{"data-svelte-h":!0}),J(A)!=="svelte-1qcm21k"&&(A.innerHTML=zl),yl=e(l),r=y(l,"P",{"data-svelte-h":!0}),J(r)!=="svelte-uvg96r"&&(r.textContent=xl),Jl=e(l),U(u.$$.fragment,l),jl=e(l),b=y(l,"P",{"data-svelte-h":!0}),J(b)!=="svelte-exhf6d"&&(b.innerHTML=ql),Ul=e(l),d=y(l,"P",{"data-svelte-h":!0}),J(d)!=="svelte-wsf1mq"&&(d.innerHTML=Fl),Tl=e(l),h=y(l,"P",{"data-svelte-h":!0}),J(h)!=="svelte-1ksq0nt"&&(h.innerHTML=Hl),wl=e(l),B=y(l,"P",{"data-svelte-h":!0}),J(B)!=="svelte-1ox26i7"&&(B.innerHTML=Ll),ol=e(l),U(f.$$.fragment,l),pl=e(l),Z=y(l,"P",{"data-svelte-h":!0}),J(Z)!=="svelte-nuq6tl"&&(Z.innerHTML=$l),il=e(l),_=y(l,"P",{"data-svelte-h":!0}),J(_)!=="svelte-erl2sb"&&(_.textContent=Pl),Il=e(l),v=y(l,"P",{"data-svelte-h":!0}),J(v)!=="svelte-1t2c7zs"&&(v.innerHTML=Dl),Cl=e(l),U(G.$$.fragment,l),cl=e(l),k=y(l,"P",{"data-svelte-h":!0}),J(k)!=="svelte-ywbycg"&&(k.innerHTML=Kl),ml=e(l),W=y(l,"P",{"data-svelte-h":!0}),J(W)!=="svelte-1a0720n"&&(W.innerHTML=Ol),Al=e(l),E=y(l,"UL",{"data-svelte-h":!0}),J(E)!=="svelte-19922wv"&&(E.innerHTML=ls),rl=e(l),N=y(l,"P",{"data-svelte-h":!0}),J(N)!=="svelte-1ilp7il"&&(N.textContent=ss),ul=e(l),U(g.$$.fragment,l),bl=e(l),Y=y(l,"UL",{"data-svelte-h":!0}),J(Y)!=="svelte-19xjy9a"&&(Y.innerHTML=Ms),dl=e(l),U(S.$$.fragment,l),hl=e(l),Q=y(l,"UL",{"data-svelte-h":!0}),J(Q)!=="svelte-15kgwc9"&&(Q.innerHTML=as),Bl=e(l),V=y(l,"P",{"data-svelte-h":!0}),J(V)!=="svelte-1x2lfz1"&&(V.textContent=ns),fl=e(l),U(R.$$.fragment,l),Zl=e(l),X=y(l,"P",{"data-svelte-h":!0}),J(X)!=="svelte-1xrpn7q"&&(X.innerHTML=es),_l=e(l),U(z.$$.fragment,l),vl=e(l),x=y(l,"P",{"data-svelte-h":!0}),J(x)!=="svelte-vmg64m"&&(x.textContent=ts),Gl=e(l),q=y(l,"P",{"data-svelte-h":!0}),J(q)!=="svelte-1mv8345"&&(q.innerHTML=ys),kl=e(l),F=y(l,"P",{"data-svelte-h":!0}),J(F)!=="svelte-1u0lrpj"&&(F.textContent=Js),Wl=e(l),U(H.$$.fragment,l),El=e(l),L=y(l,"P",{"data-svelte-h":!0}),J(L)!=="svelte-8ywxid"&&(L.textContent=js),Nl=e(l),$=y(l,"P",{"data-svelte-h":!0}),J($)!=="svelte-1nq6xgm"&&($.textContent=Us),gl=e(l),P=y(l,"P",{"data-svelte-h":!0}),J(P)!=="svelte-1sd5la0"&&(P.textContent=Ts),Yl=e(l),U(D.$$.fragment,l),Sl=e(l),ll=y(l,"P",{}),ws(ll).forEach(M),this.h()},h(){os(i,"name","hf:doc:metadata"),os(i,"content",hs)},m(l,s){rs(document.head,i),a(l,sl,s),a(l,O,s),a(l,Ml,s),T(I,l,s),a(l,al,s),T(C,l,s),a(l,nl,s),a(l,c,s),a(l,el,s),a(l,m,s),a(l,tl,s),a(l,A,s),a(l,yl,s),a(l,r,s),a(l,Jl,s),T(u,l,s),a(l,jl,s),a(l,b,s),a(l,Ul,s),a(l,d,s),a(l,Tl,s),a(l,h,s),a(l,wl,s),a(l,B,s),a(l,ol,s),T(f,l,s),a(l,pl,s),a(l,Z,s),a(l,il,s),a(l,_,s),a(l,Il,s),a(l,v,s),a(l,Cl,s),T(G,l,s),a(l,cl,s),a(l,k,s),a(l,ml,s),a(l,W,s),a(l,Al,s),a(l,E,s),a(l,rl,s),a(l,N,s),a(l,ul,s),T(g,l,s),a(l,bl,s),a(l,Y,s),a(l,dl,s),T(S,l,s),a(l,hl,s),a(l,Q,s),a(l,Bl,s),a(l,V,s),a(l,fl,s),T(R,l,s),a(l,Zl,s),a(l,X,s),a(l,_l,s),T(z,l,s),a(l,vl,s),a(l,x,s),a(l,Gl,s),a(l,q,s),a(l,kl,s),a(l,F,s),a(l,Wl,s),T(H,l,s),a(l,El,s),a(l,L,s),a(l,Nl,s),a(l,$,s),a(l,gl,s),a(l,P,s),a(l,Yl,s),T(D,l,s),a(l,Sl,s),a(l,ll,s),Ql=!0},p:Is,i(l){Ql||(w(I.$$.fragment,l),w(C.$$.fragment,l),w(u.$$.fragment,l),w(f.$$.fragment,l),w(G.$$.fragment,l),w(g.$$.fragment,l),w(S.$$.fragment,l),w(R.$$.fragment,l),w(z.$$.fragment,l),w(H.$$.fragment,l),w(D.$$.fragment,l),Ql=!0)},o(l){o(I.$$.fragment,l),o(C.$$.fragment,l),o(u.$$.fragment,l),o(f.$$.fragment,l),o(G.$$.fragment,l),o(g.$$.fragment,l),o(S.$$.fragment,l),o(R.$$.fragment,l),o(z.$$.fragment,l),o(H.$$.fragment,l),o(D.$$.fragment,l),Ql=!1},d(l){l&&(M(sl),M(O),M(Ml),M(al),M(nl),M(c),M(el),M(m),M(tl),M(A),M(yl),M(r),M(Jl),M(jl),M(b),M(Ul),M(d),M(Tl),M(h),M(wl),M(B),M(ol),M(pl),M(Z),M(il),M(_),M(Il),M(v),M(Cl),M(cl),M(k),M(ml),M(W),M(Al),M(E),M(rl),M(N),M(ul),M(bl),M(Y),M(dl),M(hl),M(Q),M(Bl),M(V),M(fl),M(Zl),M(X),M(_l),M(vl),M(x),M(Gl),M(q),M(kl),M(F),M(Wl),M(El),M(L),M(Nl),M($),M(gl),M(P),M(Yl),M(Sl),M(ll)),M(i),p(I,l),p(C,l),p(u,l),p(f,l),p(G,l),p(g,l),p(S,l),p(R,l),p(z,l),p(H,l),p(D,l)}}}const hs='{"title":"Construye tu Propio Agente de Batalla Pokémon","local":"construye-tu-propio-agente-de-batalla-pokémon","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":"🧠 Lógica Central","local":"-lógica-central","sections":[],"depth":3},{"title":"🔧 Métodos Internos Clave","local":"-métodos-internos-clave","sections":[],"depth":3}],"depth":2},{"title":"🧪 Plantilla de Agente","local":"-plantilla-de-agente","sections":[],"depth":2}],"depth":1}';function Bs(Vl){return Cs(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class Ws extends cs{constructor(i){super(),ms(this,i,Bs,ds,is,{})}}export{Ws as component};
