<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ricardoceci</title>
    <description>The latest articles on DEV Community by ricardoceci (@ricardoceci).</description>
    <link>https://dev.to/ricardoceci</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F721327%2F98cdfb8c-93b6-4be0-a21e-944050999aa6.jpg</url>
      <title>DEV Community: ricardoceci</title>
      <link>https://dev.to/ricardoceci</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ricardoceci"/>
    <language>en</language>
    <item>
      <title>Memory-Aware Shopping Agents with Strands Agents and Mem0</title>
      <dc:creator>ricardoceci</dc:creator>
      <pubDate>Thu, 09 Apr 2026 13:05:20 +0000</pubDate>
      <link>https://dev.to/aws-builders/memory-aware-shopping-agents-with-strands-agents-and-mem0-50b</link>
      <guid>https://dev.to/aws-builders/memory-aware-shopping-agents-with-strands-agents-and-mem0-50b</guid>
      <description>&lt;p&gt;&lt;em&gt;A research paper from Alibaba proposes a two-stage e-commerce agent that remembers customer preferences across sessions. In this post, you learn how to build it as a working chat app using Strands Agents, Amazon Bedrock, Mem0, and the Shopify Storefront Model Context Protocol (MCP).&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why e-commerce agents forget everything
&lt;/h2&gt;

&lt;p&gt;Most e-commerce chatbots have goldfish memory.&lt;/p&gt;

&lt;p&gt;A customer tells your assistant: &lt;em&gt;"I'm a size M, I hate synthetic fabrics, my budget is around $200."&lt;/em&gt; Three sessions later, they're back. The bot asks again. This is not only a UX annoyance. It's a conversion problem. And it's entirely avoidable.&lt;/p&gt;

&lt;p&gt;A paper published in March 2026, &lt;a href="https://arxiv.org/abs/2603.14864" rel="noopener noreferrer"&gt;Shopping Companion (arXiv:2603.14864)&lt;/a&gt; from Alibaba's international commerce team, tackles this directly. The researchers build a large language model (LLM) agent that remembers customer preferences across sessions, retrieves them before searching, and asks the customer to confirm before recommending anything.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the paper proposes
&lt;/h2&gt;

&lt;p&gt;The core idea is splitting the agent into two stages instead of one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 1, Preference Identification:&lt;/strong&gt; Before touching the catalog, the agent reads past conversation history and extracts implicit style preferences: size, fit, occasion, fabric aversions, color preferences, and budget. It surfaces a summary and asks the customer to confirm. They can correct anything before the search starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 2, Shopping Assistance:&lt;/strong&gt; With confirmed preferences in hand, the agent searches the catalog and verifies each candidate before recommending. For outfit bundles, it coordinates across products and validates budget math. The paper trains the whole pipeline end-to-end with reinforcement learning (RL). Their fine-tuned 4B model reaches 84% success on single-product tasks, surpassing GPT-4o (72%). You don't need to replicate the RL training. The inference architecture is fully buildable today.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fer9wi6mv9g6m1bka10do.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fer9wi6mv9g6m1bka10do.png" alt="Architecture diagram" width="725" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LLM&lt;/td&gt;
&lt;td&gt;Amazon Bedrock Claude Sonnet 4&lt;/td&gt;
&lt;td&gt;Pay per token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embeddings&lt;/td&gt;
&lt;td&gt;Amazon Bedrock Titan Embed v2 (via Mem0)&lt;/td&gt;
&lt;td&gt;Pay per token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-session memory&lt;/td&gt;
&lt;td&gt;Mem0 free tier&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product catalog&lt;/td&gt;
&lt;td&gt;Shopify Storefront MCP&lt;/td&gt;
&lt;td&gt;Free, no auth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat server&lt;/td&gt;
&lt;td&gt;FastAPI + uvicorn&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent framework&lt;/td&gt;
&lt;td&gt;Strands Agents (open source)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Stage 1: Cross-session memory with AWS Strands Agents and Mem0
&lt;/h2&gt;

&lt;p&gt;The paper externalizes memory into retrievable records injected into generation at runtime. In this implementation, Mem0 handles extraction, deduplication, storage, and semantic retrieval, using Amazon Bedrock Titan Embed v2 as the embedding model.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mem0_memory&lt;/code&gt; ships as a built-in tool in &lt;code&gt;strands-agents-tools&lt;/code&gt;, which means Stage 1 is a single-tool agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# agents/shopping_companion.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;strands_tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mem0_memory&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;identify_preferences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;STAGE1_SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mem0_memory&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Shopping request: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retrieve this customer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s style preferences relevant to this request.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before this can work, you need to index past conversations. Mem0 extracts structured facts from raw turns automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mem0&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MemoryClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MemoryClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MEM0_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;turns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I always size up. I find fitted styles uncomfortable.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Good to know. Sizing up for relaxed fit.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I basically live in linen when it gets warm.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Linen it is. Any fabrics to avoid?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Anything synthetic. Polyester makes me overheat.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;turns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Mem0 extracts:
# - "Customer sizes up, prefers relaxed fit"
# - "Customer prefers linen fabric"
# - "Customer avoids synthetic / polyester fabrics"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five raw turns become three clean, queryable facts. Deduplication is automatic: running twice won't create duplicates, and when a customer says "actually I moved to size L last month," Mem0 updates the existing fact rather than adding a contradiction. According to the Mem0 paper, this approach delivers 91% lower latency and 90% lower token cost compared to full-context approaches, with 26% better accuracy on the LOCOMO memory benchmark than OpenAI's memory system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 2: Live catalog search via the Shopify Storefront MCP
&lt;/h2&gt;

&lt;p&gt;The paper implements &lt;code&gt;product_search&lt;/code&gt; and &lt;code&gt;product_view&lt;/code&gt; as tools over a BM25 (Best Match 25) index. In this implementation, those tools come directly from the store via the Shopify Storefront MCP, so the catalog is always live: real prices, real stock, real variants.&lt;/p&gt;

&lt;p&gt;Every Shopify store exposes a public MCP endpoint at &lt;code&gt;https://{store}.myshopify.com/api/mcp&lt;/code&gt;. No OAuth or API key is required. The endpoint is open by design for storefront interactions. Strands has native MCP support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tools/product_tools.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;strands.tools.mcp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MCPClient&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mcp.client.streamable_http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;streamable_http_client&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_shopify_mcp_client&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SHOPIFY_STORE_DOMAIN&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/api/mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="c1"&gt;# MCPClient requires a transport callable, not a url= keyword argument
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;MCPClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;streamable_http_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;list_tools_sync()&lt;/code&gt; must be called inside the context manager. The connection is not open until you enter it. This is where Stage 2 runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# agents/shopping_companion.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_products&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;confirmed_preferences&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mcp_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_product_tools&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;mcp_client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# connection is open here — fetch tools and run agent
&lt;/span&gt;        &lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mcp_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_tools_sync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;STAGE2_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Query: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Confirmed preferences:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;confirmed_preferences&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The store's native &lt;code&gt;search_shop_catalog&lt;/code&gt; tool accepts a &lt;code&gt;context&lt;/code&gt; parameter. This is how confirmed preferences flow from Stage 1 into the catalog search:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;search_shop_catalog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxi dress&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size M, relaxed fit, linen only, midi or maxi, avoids orange&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The user intervention loop: the detail that matters most
&lt;/h2&gt;

&lt;p&gt;The paper explicitly models user intervention as a first-class part of the architecture. After Stage 1 retrieves preferences, the agent surfaces them for confirmation before Stage 2 runs. The customer can correct anything.&lt;/p&gt;

&lt;p&gt;This implementation adds one critical refinement: once you confirm preferences in a session, they persist for all follow-up requests. Stage 1 only runs once, on the first message of a new session. The distinction between &lt;code&gt;pending_preferences&lt;/code&gt; (pre-confirmation) and &lt;code&gt;confirmed_preferences&lt;/code&gt; (persisted for the session) is what makes this work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;awaiting_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="c1"&gt;# Preferences already confirmed earlier in this session:
&lt;/span&gt;    &lt;span class="c1"&gt;# skip Stage 1 and go straight to product search
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confirmed_preferences&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;recommendation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;companion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_products&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;confirmed_preferences&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confirmed_preferences&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ChatResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;recommendation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt;

    &lt;span class="c1"&gt;# First request in session: run Stage 1
&lt;/span&gt;    &lt;span class="n"&gt;preferences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;companion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;identify_preferences&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pending_preferences&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;preferences&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;awaiting_confirmation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ChatResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;awaiting_confirmation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt;

&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;awaiting_confirmation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;confirmed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;companion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_confirmation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;identified_preferences&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pending_preferences&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;user_response&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confirmed_preferences&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;confirmed&lt;/span&gt;  &lt;span class="c1"&gt;# persists for whole session
&lt;/span&gt;    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;awaiting_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;recommendation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;companion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_products&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ChatResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;recommendation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;process_confirmation&lt;/code&gt; method delegates the correction-vs-confirmation decision to the agent itself. The agent has the full context of what was identified and what the customer said, which is exactly the kind of reasoning LLMs handle well. If the response is "looks perfect," nothing gets saved to Mem0. If it's "actually I moved to size L," the new fact gets stored and confirmed preferences are updated before Stage 2 runs.&lt;/p&gt;

&lt;p&gt;The resulting conversation flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Turn 1: "I need a dress for a wedding"
  → Stage 1 runs, retrieves: size M, midi/maxi, linen, avoids orange
  → "Do these look right?"

Turn 2: "Looks perfect"
  → Stage 2 runs, returns dress recommendation
  → confirmed_preferences saved to session

Turn 3: "I liked that one. Can you find a blazer to go with it?"
  → confirmed_preferences already in session
  → Stage 1 SKIPPED, Stage 2 runs directly

Turn 4: "What about shoes?"
  → Stage 1 still SKIPPED, Stage 2 runs with same preferences
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What to build next
&lt;/h2&gt;

&lt;p&gt;The paper's main result is a 4B model that outperforms GPT-4o. This comes from RL training with a dual reward: one for how well Stage 1 extracted preferences, one for whether Stage 2's recommendation was correct. A third tool-wise reward scores each individual tool call, not only the final result. This significantly improves credit assignment in multi-turn interactions and also reduces response verbosity, because the model learns that unnecessary tool calls are penalized.&lt;/p&gt;

&lt;p&gt;Replicating that training requires labeled trajectories and GPU compute. What you get from &lt;a href="https://github.com/ricardoceci/blogs/tree/main/2026/shopping-companion" rel="noopener noreferrer"&gt;this repo&lt;/a&gt; is the full inference architecture running with Claude Sonnet 4 zero-shot. It works well in practice and gives you a production-ready foundation to layer the training on top of later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;strands-agents &lt;span class="s2"&gt;"strands-agents-tools[mem0-memory]"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    rank_bm25 fastapi uvicorn boto3 python-dotenv mem0ai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .env&lt;/span&gt;
&lt;span class="nv"&gt;AWS_DEFAULT_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-east-1
&lt;span class="nv"&gt;BEDROCK_MODEL_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;anthropic.claude-sonnet-4-20250514-v1:0
&lt;span class="nv"&gt;MEM0_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-mem0-api-key
&lt;span class="nv"&gt;MEM0_LLM_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;anthropic.claude-3-5-haiku-20241022-v1:0
&lt;span class="nv"&gt;MEM0_EMBEDDER_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amazon.titan-embed-text-v2:0
&lt;span class="nv"&gt;PRODUCT_BACKEND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;shopify
&lt;span class="nv"&gt;SHOPIFY_STORE_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-store.myshopify.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python scripts/index_history.py   &lt;span class="c"&gt;# seed sample conversation history into Mem0&lt;/span&gt;
python app.py                     &lt;span class="c"&gt;# start server at http://localhost:8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sample history includes preference sessions interleaved with unrelated conversations. This mirrors the paper's "needle in a haystack" setup, so the agent has to retrieve the right preferences from across multiple sessions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does this work with any Shopify store?&lt;/strong&gt;&lt;br&gt;
Yes. Every Shopify store has a public MCP endpoint at &lt;code&gt;https://{store}.myshopify.com/api/mcp&lt;/code&gt; enabled by default since the Summer 2025 Edition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if a customer has no memory yet?&lt;/strong&gt;&lt;br&gt;
Stage 1 returns an empty preference list and tells the customer so. Stage 2 runs with whatever the customer provides in that first message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use a model other than Claude Sonnet 4?&lt;/strong&gt;&lt;br&gt;
Yes. Strands Agents is model-agnostic. Replace &lt;code&gt;BedrockModel&lt;/code&gt; with &lt;code&gt;AnthropicModel&lt;/code&gt; or &lt;code&gt;OpenAIModel&lt;/code&gt; in one line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need GPU compute to run this?&lt;/strong&gt;&lt;br&gt;
No. This implementation runs entirely on API calls to Amazon Bedrock and Mem0. The RL training from the original paper requires GPU compute, but that is not part of this repo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is Mem0 free?&lt;/strong&gt;&lt;br&gt;
Mem0 has a free tier at &lt;a href="https://mem0.ai" rel="noopener noreferrer"&gt;mem0.ai&lt;/a&gt;. You can also run it self-hosted with a local FAISS backend by setting &lt;code&gt;USE_LOCAL_MEMORY=true&lt;/code&gt; in your &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2603.14864" rel="noopener noreferrer"&gt;Shopping Companion (arXiv:2603.14864)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://strandsagents.com" rel="noopener noreferrer"&gt;Strands Agents SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shopify.dev/docs/apps/build/storefront-mcp/servers/storefront" rel="noopener noreferrer"&gt;Shopify Storefront MCP documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mem0.ai/blog/aws-and-mem0-partner-to-bring-persistent-memory-to-next-gen-ai-agents-with-strands" rel="noopener noreferrer"&gt;AWS and Mem0 partnership announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2504.19413" rel="noopener noreferrer"&gt;Mem0 paper (arXiv:2504.19413)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ricardoceci/blogs/tree/main/2026/shopping-companion" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>shopify</category>
      <category>llm</category>
    </item>
    <item>
      <title>Lo que más me sorprendió de re:Invent 2025 (hasta ahora)</title>
      <dc:creator>ricardoceci</dc:creator>
      <pubDate>Thu, 04 Dec 2025 18:59:36 +0000</pubDate>
      <link>https://dev.to/ricardoceci/lo-que-mas-me-sorprendio-de-reinvent-2025-hasta-ahora-1afa</link>
      <guid>https://dev.to/ricardoceci/lo-que-mas-me-sorprendio-de-reinvent-2025-hasta-ahora-1afa</guid>
      <description>&lt;p&gt;Este año vine a re:Invent *&lt;em&gt;con muchas expectativas&lt;/em&gt;… y AWS no defraudó.&lt;br&gt;
Entre anuncios de modelos, agentes autónomos y nuevas formas de entrenar IA sin hipotecar tu empresa, siento que estamos entrando en otra liga.&lt;br&gt;&lt;br&gt;
Y sí: Matt Garman lo dijo en el keynote — &lt;em&gt;“The future belongs to developers”&lt;/em&gt; — y estos lanzamientos lo dejan clarísimo.&lt;/p&gt;

&lt;p&gt;Acá van los que, personalmente, más me volaron la cabeza.&lt;/p&gt;




&lt;h2&gt;
  
  
  Amazon Nova Forge — entrenar tu propio frontier model ya no es ciencia ficción
&lt;/h2&gt;

&lt;p&gt;Hasta ahora, entrenar un modelo “estilo GPT” era un privilegio para 5 empresas en el planeta.&lt;br&gt;&lt;br&gt;
Con &lt;strong&gt;Nova Forge&lt;/strong&gt;, AWS abre la puerta para que cualquier organización pueda entrenar su propio &lt;em&gt;frontier model&lt;/em&gt;, partiendo de checkpoints de la familia Nova.&lt;/p&gt;

&lt;p&gt;¿La traducción práctica?&lt;br&gt;&lt;br&gt;
Podés construir un modelo que entienda profundamente tu industria, tus datos y tus procesos… sin invertir una fortuna en GPUs ni esperar meses.&lt;/p&gt;

&lt;p&gt;Lo que más me entusiasma:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Podés mezclar tus datos reales con los datos curados de Nova.
&lt;/li&gt;
&lt;li&gt;Tiene soporte para pre-training, fine-tuning e incluso &lt;em&gt;reinforcement fine-tuning&lt;/em&gt;.
&lt;/li&gt;
&lt;li&gt;El modelo resultante se puede usar en &lt;strong&gt;Bedrock&lt;/strong&gt; como si fuera un modelo propio más del catálogo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto no es “un modelo personalizado”:&lt;br&gt;&lt;br&gt;
Es &lt;em&gt;tu propio frontier model&lt;/em&gt;, hecho a tu medida.&lt;/p&gt;

&lt;p&gt;Para los que trabajamos en e-commerce, retail, logística y automatización, esto abre una puerta gigante para crear modelos que entiendan inventarios, SKUs, productos, temporadas, comportamiento de clientes… con una precisión que un modelo genérico no puede igualar.&lt;/p&gt;




&lt;h2&gt;
  
  
  Amazon Nova 2 Omni — un solo modelo que lo hace todo
&lt;/h2&gt;

&lt;p&gt;Otro anuncio fuerte fue &lt;strong&gt;Nova 2 Omni&lt;/strong&gt;, un modelo multimodal que entiende:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;texto
&lt;/li&gt;
&lt;li&gt;imágenes
&lt;/li&gt;
&lt;li&gt;video
&lt;/li&gt;
&lt;li&gt;audio
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…y además puede &lt;strong&gt;generar texto e imágenes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lo más interesante para mí no es la multimodalidad en sí (que ya esperábamos), sino que AWS esté apostando a un &lt;em&gt;único&lt;/em&gt; modelo unificado. Eso simplifica arquitectura, desarrollo y mantenimiento.&lt;/p&gt;

&lt;p&gt;Imaginá flujos donde un cliente te manda un video, y el modelo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;lo entiende,
&lt;/li&gt;
&lt;li&gt;lo resume,
&lt;/li&gt;
&lt;li&gt;describe ítems,
&lt;/li&gt;
&lt;li&gt;genera imágenes de variantes,
&lt;/li&gt;
&lt;li&gt;y responde por texto o voz.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Todo con un solo endpoint.&lt;/p&gt;

&lt;p&gt;Estamos yendo hacia modelos más “generalistas pero especializados en ejecución”. Y eso abre posibilidades enormes para agentes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bedrock AgentCore — agentes que por fin se pueden controlar
&lt;/h2&gt;

&lt;p&gt;Si venís siguiendo los avances en agentes autónomos, sabés que el gran problema es que se vuelven… demasiado autónomos 😅&lt;/p&gt;

&lt;p&gt;AWS anunció mejoras en &lt;strong&gt;AgentCore&lt;/strong&gt; que apuntan justamente a eso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Policies&lt;/strong&gt;: reglas en lenguaje natural para definir qué puede y no puede hacer un agente.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluaciones&lt;/strong&gt; integradas: monitorean calidad, seguridad, utilidad.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejor memoria&lt;/strong&gt;: los agentes mantienen contexto de forma más natural y consistente.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La parte de &lt;em&gt;quality evaluations&lt;/em&gt; me parece clave: ya no tenés un agente que “esperás que se porte bien”; ahora tenés métricas que te dicen si realmente se está comportando como debería.&lt;/p&gt;

&lt;p&gt;Esto es fundamental para llevar agentes a producción en empresas reales — no en demos.&lt;/p&gt;




&lt;h2&gt;
  
  
  Los tres “Frontier Agents”, y el que puede programar durante días
&lt;/h2&gt;

&lt;p&gt;AWS presentó tres agentes que llama “frontier agents, pensados para cambiar la forma en la que desarrollamos, aseguramos y operamos software.&lt;/p&gt;

&lt;p&gt;El que más ruido hizo: &lt;strong&gt;Kiro Autonomous Agent&lt;/strong&gt;, un agente que puede codear durante horas o días, de forma autónoma, siguiendo un objetivo.&lt;/p&gt;

&lt;p&gt;No es un Copilot mejorado.&lt;br&gt;&lt;br&gt;
Es otra categoría.&lt;/p&gt;

&lt;p&gt;La apuesta de AWS es clara:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;el futuro del desarrollo no es escribir código, sino explicar lo que querés construir&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Todavía está en preview, pero conceptualmente es enorme. Combina modelos Nova + AgentCore + memoria + políticas + herramientas. Es decir: un agente que realmente puede &lt;em&gt;trabajar&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Para quienes construimos productos, integraciones y automatizaciones, esto es una señal fuerte de hacia dónde va la industria.&lt;/p&gt;




&lt;h2&gt;
  
  
  En resumen
&lt;/h2&gt;

&lt;p&gt;Este re:Invent marca un cambio de etapa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IA más personalizada (Nova Forge)
&lt;/li&gt;
&lt;li&gt;IA más capaz (Nova 2 Omni)
&lt;/li&gt;
&lt;li&gt;IA más controlada (AgentCore)
&lt;/li&gt;
&lt;li&gt;IA más autónoma (Frontier Agents)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es el combo completo: poder, personalización, seguridad y autonomía.&lt;br&gt;&lt;br&gt;
Y todo dentro del ecosistema que ya usamos: Bedrock, SageMaker, IAM, CloudWatch, etc.&lt;/p&gt;

&lt;p&gt;El mensaje es claro:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;los developers ahora tenemos herramientas que hace dos años eran ciencia ficción&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>MCP en acción: integra datos del sistema en tus modelos generativos</title>
      <dc:creator>ricardoceci</dc:creator>
      <pubDate>Fri, 09 May 2025 15:42:13 +0000</pubDate>
      <link>https://dev.to/aws-espanol/mcp-en-accion-integra-datos-del-sistema-en-tus-modelos-generativos-2c9c</link>
      <guid>https://dev.to/aws-espanol/mcp-en-accion-integra-datos-del-sistema-en-tus-modelos-generativos-2c9c</guid>
      <description>&lt;p&gt;En 2025, la velocidad con la que aparecen nuevos conceptos y funcionalidades en el campo de la inteligencia artificial generativa hace que parezca que han pasado décadas desde el lanzamiento de la primera versión de ChatGPT. Sin embargo, han pasado menos de tres años.&lt;/p&gt;

&lt;p&gt;A fines de 2024, &lt;a href="https://www.anthropic.com/" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, los creadores de Claude, publicaron el &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; como código abierto. Aunque inicialmente pasó desapercibido, hoy está presente en casi todos los artículos, herramientas o funcionalidades relacionadas con la IA generativa. MCP se menciona en todas partes.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es MCP?
&lt;/h2&gt;

&lt;p&gt;MCP (Model Context Protocol) es una especificación de código abierto desarrollada por Anthropic.&lt;/p&gt;

&lt;p&gt;Según su documentación oficial, MCP actúa como el &lt;em&gt;“USB-C para la IA”&lt;/em&gt;: una interfaz unificada que permite conectar modelos de lenguaje con herramientas externas de forma estandarizada.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;La verdadera ventaja de MCP radica en la estandarización.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Técnicamente, un LLM que actúa como cliente puede conectarse a un servidor MCP para acceder a datos o funcionalidades externas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Componentes estándar del protocolo MCP
&lt;/h2&gt;

&lt;p&gt;El Model Context Protocol (MCP) se basa en tres componentes fundamentales que permiten a los servidores exponer capacidades a los clientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Recursos&lt;/strong&gt;: Datos estructurados que proporcionan contexto adicional al modelo. Pueden incluir contenidos de archivos, registros de bases de datos, respuestas de APIs, entre otros. Los recursos son controlados por la aplicación y pueden ser seleccionados explícitamente por el usuario o automáticamente por el cliente. &lt;a href="https://modelcontextprotocol.io/docs/concepts/resources" rel="noopener noreferrer"&gt;Más Info&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prompts&lt;/strong&gt;: Plantillas reutilizables que definen interacciones comunes con el modelo. Permiten estandarizar y compartir flujos de trabajo, y pueden aceptar argumentos dinámicos, incluir contexto de recursos y guiar procesos específicos. &lt;a href="https://modelcontextprotocol.io/docs/concepts/prompts" rel="noopener noreferrer"&gt;Más Info&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Herramientas&lt;/strong&gt;: Funciones ejecutables que el modelo puede invocar para realizar acciones, como interactuar con sistemas externos, realizar cálculos o ejecutar comandos. Las herramientas son controladas por el modelo y pueden ser descubiertas e invocadas automáticamente por este.&lt;a href="https://modelcontextprotocol.io/docs/concepts/tools" rel="noopener noreferrer"&gt;Más Info&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“MCP proporciona una estructura modular que organiza claramente la entrada, el conocimiento y la capacidad de acción del modelo.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ¿Por qué es relevante?
&lt;/h2&gt;

&lt;p&gt;Gracias a su estructura modular, MCP permite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Separación de responsabilidades&lt;/strong&gt;: cada bloque tiene un propósito específico.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mayor claridad contextual&lt;/strong&gt;: el modelo comprende mejor sus objetivos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agentes más avanzados&lt;/strong&gt;: habilita el uso de memoria, herramientas y razonamiento intermedio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidad&lt;/strong&gt;: permite construir arquitecturas modulares y sostenibles.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;No estás escribiendo un solo prompt. Estás diseñando un protocolo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Ejemplo práctico
&lt;/h2&gt;

&lt;p&gt;Si le preguntas a un modelo cuál es el uso actual de la CPU de tu computadora, probablemente no lo sepa. No tiene acceso a tu sistema operativo, ya que su función principal es generar texto, no interactuar con hardware.&lt;/p&gt;

&lt;p&gt;Ahí es donde entra MCP: permite que el modelo acceda a información externa a través de herramientas definidas por el servidor.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cómo construir un servidor MCP en 4 pasos
&lt;/h2&gt;

&lt;p&gt;Puedes crear un servidor MCP utilizando Python y la biblioteca &lt;a href="https://pypi.org/project/fastmcp/" rel="noopener noreferrer"&gt;fastmcp&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Crear &lt;code&gt;server.py&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mcp.server.fastmcp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastMCP&lt;/span&gt;

&lt;span class="n"&gt;mcp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastMCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sys-monitor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@mcp.tool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_system_stats&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;cpu_percent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cpu_percent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;virtual_mem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;virtual_memory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu_percent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cpu_percent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_total_gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;virtual_mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_used_gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;virtual_mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_percent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;virtual_mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;percent&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Crear &lt;code&gt;requirements.txt&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psutil&amp;gt;=5.9.0
fastmcp&amp;gt;=0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Crear el &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "server.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Construir la imagen de Docker (opcional)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: esta configuración reportará el uso de CPU del contenedor, no del sistema anfitrión. A fines educativos, sigue siendo válido.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; cpusage &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conectar el servidor MCP a un modelo
&lt;/h2&gt;

&lt;p&gt;Este ejemplo utiliza &lt;strong&gt;Claude Desktop&lt;/strong&gt;, pero también es compatible con Amazon Q CLI u otros LLM que soporten MCP.&lt;/p&gt;

&lt;p&gt;Sigue la &lt;a href="https://modelcontextprotocol.io/quickstart/user" rel="noopener noreferrer"&gt;guía oficial&lt;/a&gt; para la integración.&lt;/p&gt;

&lt;p&gt;Si tu archivo &lt;code&gt;claude_desktop_config.json&lt;/code&gt; está vacío, agregá lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cpusage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--rm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"cpusage"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si deseas ejecutar el servidor directamente con Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cpusage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ruta/al/server.py"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;También podés reemplazar &lt;code&gt;"python"&lt;/code&gt; por &lt;code&gt;uv&lt;/code&gt; u otro comando si estás usando un entorno virtual.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si ya existen otros servidores definidos, simplemente agregá el bloque correspondiente.&lt;/p&gt;

&lt;p&gt;Reiniciá Claude Desktop. ¡Listo!&lt;/p&gt;

&lt;h2&gt;
  
  
  Demostración
&lt;/h2&gt;

&lt;p&gt;Ve un video con la demo &lt;a href="https://www.youtube.com/watch?v=WXc6Mcut-OQ&amp;amp;ab_channel=Surfeandolanube" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Cómo lo estoy usando
&lt;/h2&gt;

&lt;p&gt;Estoy utilizando MCP en proyectos sobre AWS que integran modelos con bases de datos y herramientas personalizadas. Esta estructura me permite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Definir herramientas disponibles&lt;/li&gt;
&lt;li&gt;Proporcionar contexto persistente y actualizado&lt;/li&gt;
&lt;li&gt;Establecer límites operativos claros&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Además, con un poco de creatividad, es fácilmente portable a otras plataformas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;MCP no es solo una forma distinta de estructurar prompts: es una forma de diseñar la arquitectura cognitiva de tus agentes.&lt;/p&gt;

&lt;p&gt;Si estás trabajando con GenAI en 2025 y aún no exploraste MCP, ahora es el momento.&lt;/p&gt;

</description>
      <category>genai</category>
      <category>mcp</category>
      <category>llm</category>
    </item>
    <item>
      <title>Hands on MCP: Extending LLMs with Real-Time Data</title>
      <dc:creator>ricardoceci</dc:creator>
      <pubDate>Fri, 09 May 2025 15:39:57 +0000</pubDate>
      <link>https://dev.to/aws-builders/mcp-in-practice-extending-llms-with-real-time-data-4f6f</link>
      <guid>https://dev.to/aws-builders/mcp-in-practice-extending-llms-with-real-time-data-4f6f</guid>
      <description>&lt;p&gt;In 2025, the pace at which new concepts and features appear in the field of generative AI makes it feel like decades have passed since the launch of the first version of ChatGPT. However, it's been less than three years.&lt;/p&gt;

&lt;p&gt;In late 2024, &lt;a href="https://www.anthropic.com/" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, the creators of Claude, released the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; as open source. Although it initially went unnoticed, today it’s present in almost every article, tool, or feature related to generative AI. MCP is mentioned everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is MCP?
&lt;/h2&gt;

&lt;p&gt;MCP (Model Context Protocol) is an open-source specification developed by Anthropic.&lt;/p&gt;

&lt;p&gt;According to its official documentation, MCP acts like the &lt;em&gt;“USB-C for AI”&lt;/em&gt;: a unified interface that allows language models to connect with external tools in a standardized way.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The real advantage of MCP lies in standardization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Technically, an LLM acting as a client can connect to an MCP server to access external data or functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standard Components of the MCP Protocol
&lt;/h2&gt;

&lt;p&gt;The Model Context Protocol (MCP) is based on three fundamental components that allow servers to expose capabilities to clients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;: Structured data that provides additional context to the model. They may include file contents, database records, API responses, and more. Resources are controlled by the application and can be explicitly selected by the user or automatically by the client. &lt;a href="https://modelcontextprotocol.io/docs/concepts/resources" rel="noopener noreferrer"&gt;More Info&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prompts&lt;/strong&gt;: Reusable templates that define common interactions with the model. They allow standardization and sharing of workflows, and can accept dynamic arguments, include resource context, and guide specific processes. &lt;a href="https://modelcontextprotocol.io/docs/concepts/prompts" rel="noopener noreferrer"&gt;More Info&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tools&lt;/strong&gt;: Executable functions that the model can invoke to perform actions, such as interacting with external systems, performing calculations, or executing commands. Tools are controlled by the model and can be automatically discovered and invoked. &lt;a href="https://modelcontextprotocol.io/docs/concepts/tools" rel="noopener noreferrer"&gt;More Info&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“MCP provides a modular structure that clearly organizes the model’s input, knowledge, and ability to act.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why is it relevant?
&lt;/h2&gt;

&lt;p&gt;Thanks to its modular structure, MCP allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Separation of concerns&lt;/strong&gt;: each block has a specific purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Greater contextual clarity&lt;/strong&gt;: the model better understands its goals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More advanced agents&lt;/strong&gt;: enables memory, tools, and intermediate reasoning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: allows building modular and sustainable architectures.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You're not just writing a prompt. You're designing a protocol.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Practical Example
&lt;/h2&gt;

&lt;p&gt;If you ask a model what your computer’s current CPU usage is, it probably won’t know. It has no access to your operating system, since its main function is to generate text, not interact with hardware.&lt;/p&gt;

&lt;p&gt;That’s where MCP comes in: it allows the model to access external information through tools defined by the server.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Build an MCP Server in 4 Steps
&lt;/h2&gt;

&lt;p&gt;You can create an MCP server using Python and the &lt;a href="https://pypi.org/project/fastmcp/" rel="noopener noreferrer"&gt;fastmcp&lt;/a&gt; library.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create &lt;code&gt;server.py&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mcp.server.fastmcp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastMCP&lt;/span&gt;

&lt;span class="n"&gt;mcp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastMCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sys-monitor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@mcp.tool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_system_stats&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;cpu_percent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cpu_percent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;virtual_mem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;virtual_memory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu_percent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cpu_percent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_total_gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;virtual_mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_used_gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;virtual_mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_percent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;virtual_mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;percent&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Create &lt;code&gt;requirements.txt&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psutil&amp;gt;=5.9.0
fastmcp&amp;gt;=0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Create the &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "server.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Build the Docker Image (Optional)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: this setup will report CPU usage of the container, not the host system. For educational purposes, it's still valid.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; cpusage &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Connecting the MCP Server to a Model
&lt;/h2&gt;

&lt;p&gt;This example uses &lt;strong&gt;Claude Desktop&lt;/strong&gt;, but it's also compatible with Amazon Q CLI or other LLMs that support MCP.&lt;/p&gt;

&lt;p&gt;Follow the &lt;a href="https://modelcontextprotocol.io/quickstart/user" rel="noopener noreferrer"&gt;official guide&lt;/a&gt; for integration.&lt;/p&gt;

&lt;p&gt;If your &lt;code&gt;claude_desktop_config.json&lt;/code&gt; file is empty, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cpusage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--rm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"cpusage"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run the server directly with Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cpusage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"path/to/server.py"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can also replace &lt;code&gt;"python"&lt;/code&gt; with &lt;code&gt;uv&lt;/code&gt; or another command if using a virtual environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If other servers are already defined, simply add the corresponding block.&lt;/p&gt;

&lt;p&gt;Restart Claude Desktop. Done!&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Video with a demo &lt;a href="https://www.youtube.com/watch?v=WXc6Mcut-OQ" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How I'm Using It
&lt;/h2&gt;

&lt;p&gt;I’m using MCP in AWS-based projects that integrate models with databases and custom tools. This structure allows me to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define available tools&lt;/li&gt;
&lt;li&gt;Provide persistent and updated context&lt;/li&gt;
&lt;li&gt;Set clear operational boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, with a bit of creativity, it’s easily portable to other platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;MCP is not just a different way to structure prompts: it’s a way to design the cognitive architecture of your agents.&lt;/p&gt;

&lt;p&gt;If you're working with GenAI in 2025 and haven't explored MCP yet, now is the time.&lt;/p&gt;

</description>
      <category>genai</category>
      <category>llm</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Creación de un agente de cafetería con Amazon Bedrock y Shopify</title>
      <dc:creator>ricardoceci</dc:creator>
      <pubDate>Fri, 25 Oct 2024 21:35:03 +0000</pubDate>
      <link>https://dev.to/aws-espanol/creacion-de-un-agente-de-cafeteria-con-amazon-bedrock-y-shopify-2i4f</link>
      <guid>https://dev.to/aws-espanol/creacion-de-un-agente-de-cafeteria-con-amazon-bedrock-y-shopify-2i4f</guid>
      <description>&lt;p&gt;Hoy te explicaré cómo poner manos a la obra con Bedrock de manera segura y confiable y de paso, aprender un poco sobre café.&lt;/p&gt;

&lt;p&gt;Aprenderás cómo consumir la &lt;a href="https://docs.aws.amazon.com/es_es/bedrock/latest/userguide/what-is-bedrock.html" rel="noopener noreferrer"&gt;API de Amazon Bedrock&lt;/a&gt; de modelos de Texto y Multimodales utilizando Python para poder generar nombres, logo y menú para tu cafetería y para poder crear un agente que se conecta a una API de Shopify para tomar pedidos.&lt;/p&gt;

&lt;p&gt;Shopify es (a mi criterio) la mejor plataforma de eCommerce que existe.&lt;/p&gt;

&lt;p&gt;Y así como AWS, &lt;a href="https://shopify.com" rel="noopener noreferrer"&gt;Shopify&lt;/a&gt; tiene una API para todo y una &lt;a href="https://shopify.dev/" rel="noopener noreferrer"&gt;plataforma para desarrolladores&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por último crearás un frontend utilizando Streamlit para dar una experiencia de usuario única y darle vida a tu agente.&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Indice
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Invocando la API de Bedrock&lt;/li&gt;
&lt;li&gt;Creación de un agente de Amazon Bedrock que interactúa con Shopify&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧐 Invocando la API de Amazon Bedrock para generar nombres, logo y menú para tu cafetería&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;El momento de abrir una cafetería o de tener ideas creativas para el negocio que fuese es una excelente oportunidad para apoyarse en la IA Generativa (GenAI) y sacar su máximo provecho.&lt;/p&gt;

&lt;p&gt;A través de Amazon Bedrock puedes hacer uso de ella, pero... ¿Cómo se consume ese servicio?&lt;/p&gt;

&lt;p&gt;Todo servicio en AWS tiene una API, y Amazon Bedrock no es la excepción, a continuación te explico cómo consumir la API de Amazon Bedrock a través de un ejemplo para generar nombres y un menú para una Cafetería al paso.&lt;/p&gt;

&lt;p&gt;Y además te muestro cómo consumir un modelo multimodal capaz de analizar imágenes.&lt;/p&gt;

&lt;p&gt;Instrucciones para programar un script en Python para ejecutar localmente o en una función Lambda para invocar a Amazon Bedrock:&lt;/p&gt;

&lt;p&gt;Primero debes habilitar el acceso a los modelos en Bedrock &lt;a href="https://docs.aws.amazon.com/es_es/bedrock/latest/userguide/model-access-modify.html" rel="noopener noreferrer"&gt;Instrucciones aqui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Requisitos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Una cuenta en AWS, si no tienes una cuenta, puedes abrir una &lt;a href="https://signin.aws.amazon.com/signup?request_type=register" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;AWS CLI &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;Instrucciones aqui&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Python 3.11 o superior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Paso 1) Crear un entorno virtual de Python &lt;a href="https://docs.python.org/es/3.12/tutorial/venv.html" rel="noopener noreferrer"&gt;Instrucciones aqui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la carpeta bedrock_examples de &lt;a href="https://github.com/ricardoceci/hands-on-bedrock" rel="noopener noreferrer"&gt;este repositorio&lt;/a&gt; encontrarás diferentes ejemplos utilizados a continuación para invocar el modelo fundacional.&lt;/p&gt;

&lt;p&gt;En la carpeta prompts encontrarás los prompts de ejemplo, que vas a poder utilizar para generar El nombre, el Menú y un prompt para pasarle a un modelo de generación de imágenes que podrás invocar tanto en el &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/playgrounds.html" rel="noopener noreferrer"&gt;playground de Amazon Bedrock&lt;/a&gt; cómo invocando la API desde Python.&lt;/p&gt;

&lt;p&gt;Paso 2) Instalar los requerimientos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paso 3) Configurar Boto3 &lt;a href="https://aws.amazon.com/es/sdk-for-python/" rel="noopener noreferrer"&gt;Mas info sobre boto3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aqui configuro el cliente de AWS indicandole que utilice el perfil genaiday instalado en mi computadora y llamo al cliente de &lt;strong&gt;bedrock-runtime&lt;/strong&gt; que me va a permitir invocar al modelo fundacional.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#Cambiar la region y el perfil de AWS
&lt;/span&gt;&lt;span class="n"&gt;aws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;genaiday&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bedrock-runtime&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paso 4) Ejemplo: Invocar modelo de texto&lt;/p&gt;

&lt;p&gt;Esta función llama al método &lt;strong&gt;invoke_model&lt;/strong&gt; y le paso el prompt indicado por el usuario y le devuelvo la respuesta&lt;/p&gt;

&lt;p&gt;La parte más importante son los mensajes enviados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;prompt&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic.claude-3-haiku-20240307-v1:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;#esta función es para llamar un modelo de texto
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic_version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock-2023-05-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
                &lt;span class="p"&gt;}]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;modelId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modelId&lt;/span&gt;
    &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;contentType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contentType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response_body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response_body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Haiku&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;call_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estoy buscando armar un local de café al paso, dame 5 nombres para un local.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paso 5) Ejemplo: Invocar a un modelo multimodal.&lt;/p&gt;

&lt;p&gt;Aquí el proceso es similar, solo que &lt;strong&gt;hay que agregar el mime type&lt;/strong&gt; del archivo enviado, para esto hay una función que en base al nombre del archivo obtiene el mimetype&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_mime_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Este hack es para versiones de python anteriores a 3.13
&lt;/span&gt;    &lt;span class="c1"&gt;# Esta función lee el mime type de un archivo
&lt;/span&gt;    &lt;span class="n"&gt;mimetypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image/webp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.webp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mime_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mimetypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;guess_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mime_type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego para invocar al modelo, los mensajes deben ser los siguientes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                     &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;base64&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;media_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;read_mime_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;caption&lt;/span&gt;
            &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La invocación del modelo queda así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_multimodal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic.claude-3-haiku-20240307-v1:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;#esta funcion es para llamar a un modelo multimodal con una imagen y un texto
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic_version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock-2023-05-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                     &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;base64&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;media_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;read_mime_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;caption&lt;/span&gt;
            &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;modelId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modelId&lt;/span&gt;
    &lt;span class="n"&gt;accept&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;contentType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contentType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response_body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response_body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pic_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./meetup_test_image.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;caption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cuantas personas hay en la imagen? cuantas laptos ves? cuantos usan gorro o sombrero?, de que color es el hoddie de la primer persona a la derecha de la foto?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Haiku&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;call_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pic_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic.claude-3-haiku-20240307-v1:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sonnet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;call_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pic_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic.claude-3-sonnet-20240229-v1:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🏁 Creación de un agente de Amazon Bedrock que interactúa con Shopify &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Para crear un agente de Amazon Bedrock:&lt;/p&gt;

&lt;p&gt;Asegurate de tener los modelos de Bedrock que quieras usar con el acceso habilitado &lt;a href="https://docs.aws.amazon.com/es_es/bedrock/latest/userguide/model-access-modify.html" rel="noopener noreferrer"&gt;Instrucciones aqui&lt;/a&gt;, en este caso utilizaremos Claude 3 Haiku y Sonnet&lt;/p&gt;

&lt;p&gt;Luego crear el agente de Bedrock en la consola de AWS:&lt;/p&gt;

&lt;p&gt;1) Ir al servicio Bedrock&lt;br&gt;
2) Agentes&lt;br&gt;
3) Crear agente&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8miwnegn4u47swv9cas.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8miwnegn4u47swv9cas.jpg" alt="Crear agente" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) Darle un nombre al agente, en nuestro caso "Pausa-Cafetera-Agente&lt;br&gt;
5) La descripción es opcional.&lt;br&gt;
6) Uno de los pasos más importantes es elegir el modelo fundacional que va a hacer que nuestro agente funcione adecuadamente, si deseas saber cómo hacer para elegir el mejor modelo que se adapte a tu caso de uso &lt;a href="https://docs.aws.amazon.com/es_es/bedrock/latest/userguide/model-evaluation.html" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; tienes una guía sobre el servicio Amazon Bedrock Model Evaluation .&lt;br&gt;
7) El siguiente paso es el prompt que va a guiar a tu modelo, aqui tienes que ser lo más preciso posible y sacar a relucir tus habilidades como prompt engineer, si no sabes por donde comenzar, te recomiendo visitar &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-engineering-guidelines.html" rel="noopener noreferrer"&gt;esta guia&lt;/a&gt; donde vas a encontrar las mejores guidelines para el modelo que estes utilizando, y además otro recurso muy útil es &lt;a href="https://console.anthropic.com/dashboard" rel="noopener noreferrer"&gt;la consola de anthropic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1sizfmusmujwxh5jmxl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1sizfmusmujwxh5jmxl.jpg" alt="Crear agente Paso 2" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este es el prompt que utilicé para el agente de ejemplo, te recomiendo escribir el prompt en inglés dado que los modelos fueron entrenados en inglés y a veces escribir en el idioma de origen de entrenamiento ayuda a evitar comportamientos erroneos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a helpful Bedrock agent working at a coffee shop.

Your goal is to assist customers in placing orders, offering them combos and creating orders by consuming a Shopify API.

When a customer interacts with you, greet them politely and ask how you can help them today.

If they indicate that they want to place an order, start by offering them popular combos or bundles that your coffee shop offers.

Before offering any product make sure to get the list of available products from the API.

Do not offer any product that is not in our list of products, never ask the customer for any recommendations.

If the customer expresses interest in a combo, you have to provide more details about the items included and the price, never ask for details to the customer, you are the one who knows about the products and combos.

Throughout the ordering process, be friendly and patient. If the customer is unsure or has questions, provide clear explanations to help them make a decision. Once the customer has finalized their order, confirm the details with them and let them know you'll be placing the order through the Shopify API.

Before creating the order through the API make sure to ask the customer for his/her name, never assume you know it.

When creating the order through the API, make sure to accurately capture all the items the customer requested, along with any customizations or special instructions they provided.

It's important to note that you should respond to the customer in their preferred language. If they initiate the conversation in a language other than English, reply in that same language to ensure smooth and effective communication.

Your goal is to provide an excellent customer experience by offering helpful recommendations, answering questions, and accurately processing orders through the Shopify API. Remember to be polite, patient, and adapt your language to match the customer's preference.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;8) Configuración adicional, debes permitir al agente que capture input del usuario, dado que seguramente le falte información para procesar la orden, por ejemplo: Necesitará preguntar por los productos que el cliente desea, el nombre, entre otras cosas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9ccov86bjmzriwv29zm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9ccov86bjmzriwv29zm.jpg" alt="Crear agente Paso 3" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;9) Grupos de acción: Un grupo de acción define las acciones en las que el agente puede ayudar al usuario. Por ejemplo, puedes definir un grupo de acciones que diga TomarPedido que puede tener las siguientes acciones&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Listar productos&lt;/li&gt;
&lt;li&gt;Procesar Pedido&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para crear un grupo de accion vas a necesitar para cada acción:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El nombre&lt;/li&gt;
&lt;li&gt;Los parámetros&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Los grupos de acción para ejecutarse generalmente invocan una función Lambda, desde Bedrock puedes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crear una función lambda desde la consola de Bedrock (Seleccionar Creación rápida de una función lambda)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyqe3pzwyd9wl47rh10d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyqe3pzwyd9wl47rh10d.jpg" alt="Crear agente Paso 4" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elegir una funcion lambda ya creada &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/agents-lambda.html" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; las instrucciones de cómo es el evento y la respuesta esperada por cada action group (grupo de acción)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si eliges crear la función lambda desde la consola de Bedrock, se creará una función en python con un código fuente básico que luego deberás modificar, en este &lt;a href="https://github.com/ricardoceci/hands-on-bedrock/" rel="noopener noreferrer"&gt;repo&lt;/a&gt; en el archivo agents/action_group/lambda.py tienes el código de ejemplo modificado para que funcione con el agente.&lt;/p&gt;

&lt;p&gt;Estas son las variables que te entregarán la información necesaria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;function&lt;/strong&gt;: es el nombre de la acción invocada, en el caso del ejemplo puede ser: get_products (para listar productos), y place_order (para generar la orden en Shopify)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;parameters&lt;/strong&gt;: es un diccionario de parámetros.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En el siguiente ejemplo puedes observar que hay dos acciones:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvz3cisxuirczqjfl261.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvz3cisxuirczqjfl261.jpg" alt="Crear agente Paso 5" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvz3cisxuirczqjfl261.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvz3cisxuirczqjfl261.jpg" alt="Crear agente Paso 6" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;get_products que no requiere ningun parámetro&lt;/li&gt;
&lt;li&gt;place_order que lleva 3 parámetros:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parametro&lt;/th&gt;
&lt;th&gt;Descripcion&lt;/th&gt;
&lt;th&gt;Tipo&lt;/th&gt;
&lt;th&gt;Obligatorio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;customerEmail&lt;/td&gt;
&lt;td&gt;Email of the customer&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;customerName&lt;/td&gt;
&lt;td&gt;Name of the customer&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;products&lt;/td&gt;
&lt;td&gt;SKUs and quantities to add to the cart in the format [{ variantId: variantId, quantity: QUANTITY }]&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Entonces, por ejemplo cuando se llame a la función get_products en la función lambda se maneja de esta manera:&lt;/p&gt;

&lt;p&gt;Hay una función get_products definida que será la encargada de hacer la query a la API de Shopify (A fines didácticos retornamos todos los productos)&lt;/p&gt;

&lt;p&gt;Si quieres que esto funcione en Shopify debes reemplazar las siguientes variables por las de tu tienda:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;access_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;shpat_XXXXX&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;


&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://XXXXXXX.myshopify.com/admin/api/2024-10/graphql.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_products&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

   &lt;span class="c1"&gt;# Let's query all the products from the Shopify API paginate through the results and store them in a list and return it
&lt;/span&gt;    &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        {
          products(first: 10%s) {
            pageInfo {
              hasNextPage
            }
            edges {
              cursor
              node {
                id
                title
                description
                variants(first: 10) {
                  edges {
                    node {
                        id
                        title
                        sku
                        price
                    }
                  }
                }
              }
            }
          }
        }
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, after: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;products&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;edges&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;node&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;products&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pageInfo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hasNextPage&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;products&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;edges&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cursor&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego en el handler de la función lambda, se verifica el nombre de la función llamada y se devuelve la respuesta con el formato que el action_group necesita:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;actionGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;actionGroup&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;function&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="c1"&gt;# Execute your business logic here. For more information, refer to: https://docs.aws.amazon.com/bedrock/latest/userguide/agents-lambda.html
&lt;/span&gt;
    &lt;span class="nf"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;get_products&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_products&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;responseBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los fragmentos de código expuestos anteriormente son parte de la función lambda que se encuentra &lt;a href="https://github.com/ricardoceci/hands-on-bedrock/blob/master/agents/action_group/lambda.py" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;10) Presionar Guardar y Salir, y listo!, ya el agente esta listo para ser probado.&lt;/p&gt;

&lt;h2&gt;
  
  
  El Agente en acción
&lt;/h2&gt;

&lt;p&gt;Lo siguiente es probar el agente y validar que funcione, desde Bedrock puedes hacer las pruebas del agente, y si durante la conversación clickeas "Ver traza o Show Trace" te va a ir mostrando el proceso de razonamiento, aqui es donde debes prestar especial atención y hacer los ajustes que creas necesarios en el prompt o bien buscar otro modelo si ves que el que elgiste no funciona como esperabas.&lt;/p&gt;

&lt;p&gt;Una vez que estes conforme con el agente, puedes crear un Alias, un alias es un ID a través del cual vas a poder invocar al agente desde la API de Amazon Bedrock, cuando crees el alias, te va a crear una versión del agente automáticamente, o puedes apuntar a una versión ya existente, tener diferentes alias y diferentes versiones te va a ayudar a controlar el proceso de despliegue del agente, por ejemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Puedes tener un alias "development" que va a ir a las ultimas pruebas del Agente&lt;/li&gt;
&lt;li&gt;Un alias "preprod" que sería el agente en modo pre producción&lt;/li&gt;
&lt;li&gt;Un alias "prod" y este es el agente live.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Luego solo restaría apuntar el alias de producción correspondiente a la versión que desees que este en vivo.&lt;/p&gt;

&lt;p&gt;Cómo invocar el agente&lt;/p&gt;

&lt;p&gt;Para esto, en la carpeta &lt;a href="https://github.com/ricardoceci/hands-on-bedrock/tree/master/agents/frontend" rel="noopener noreferrer"&gt;agents/frontend&lt;/a&gt; he dejado un archivo que se llama agent.py.&lt;/p&gt;

&lt;p&gt;Este desarrollo utiliza &lt;a href="https://streamlit.io/" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt;, un poderoso framework para realizar aplicaciones de muestra de machine learning&lt;/p&gt;

&lt;p&gt;La parte del código que hace la invocación al agente es la siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;aws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;genaiday&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bedrock-agent-runtime&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;invokeAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;agent_alias_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;agentId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;agentAliasId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent_alias_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;inputText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;sessionId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utilizamos boto3 para consumir la API de AWS, llamamos al bedrock-agent-runtime cliente para poder hacer la invocación del agente.&lt;/p&gt;

&lt;p&gt;Los parámetros que necesitamos pasarle son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agentId&lt;/li&gt;
&lt;li&gt;agentAliasId&lt;/li&gt;
&lt;li&gt;inputText (el prompt)&lt;/li&gt;
&lt;li&gt;sessionId (la sesión, para identificar las conversaciones)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En este ejemplo, las variables las estoy definiendo aqui:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;agent_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock_agent_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;agent_alias_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent Alias&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock_agent_alias&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;session_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sesion Id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Instalación:
&lt;/h2&gt;

&lt;p&gt;Primero debes habilitar el acceso a los modelos en Bedrock &lt;a href="https://docs.aws.amazon.com/es_es/bedrock/latest/userguide/model-access-modify.html" rel="noopener noreferrer"&gt;Instrucciones aqui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Requisitos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS CLI &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;Instrucciones aqui&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Python 3.11 o superior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Te recomiendo crear un entorno virtual de Python &lt;a href="https://docs.python.org/es/3.12/tutorial/venv.html" rel="noopener noreferrer"&gt;Instrucciones aqui&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ejecución
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;streamlit run agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto comenzará a ejecutar streamlit en el puerto 8501 y puedes visitar la siguiente URL: &lt;a href="http://localhost:8501/" rel="noopener noreferrer"&gt;http://localhost:8501/&lt;/a&gt; para ver el frontend que invocará al agente&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvi6x3ruedq4euvjmynx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvi6x3ruedq4euvjmynx.jpg" alt="Demo Frontend con Streamlit" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Si has seguido todos los pasos has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumido la API de Amazon Bedrock desde el Playground de Bedrock y desde Python&lt;/li&gt;
&lt;li&gt;Has invocado modelos fundacionales de texto y multimodales&lt;/li&gt;
&lt;li&gt;Has creado un agente desde 0 que consume una API de Shopify&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Algunos links para que sigas tu camino dentro de GenerativeAI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://catalog.workshops.aws/building-gen-ai-apps/en-US" rel="noopener noreferrer"&gt;Workshop AWS generative AI&lt;/a&gt;&lt;br&gt;
&lt;a href="https://aws.amazon.com/es/bedrock/knowledge-bases/" rel="noopener noreferrer"&gt;Bedrock Knowledge Bases&lt;/a&gt;&lt;br&gt;
&lt;a href="https://console.anthropic.com/dashboard" rel="noopener noreferrer"&gt;Anthropic Console&lt;/a&gt; (Para hacer debug de nuestros prompts)&lt;br&gt;
&lt;a href="https://community.aws" rel="noopener noreferrer"&gt;Community.aws&lt;/a&gt; (más artículos generados por y para la comunidad)&lt;/p&gt;

</description>
      <category>bedrock</category>
      <category>genai</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Llevando la gestión de Shopify al siguiente nivel con GenAI</title>
      <dc:creator>ricardoceci</dc:creator>
      <pubDate>Mon, 11 Mar 2024 10:53:15 +0000</pubDate>
      <link>https://dev.to/aws-espanol/llevando-la-gestion-de-shopify-al-siguiente-nivel-con-genai-2bje</link>
      <guid>https://dev.to/aws-espanol/llevando-la-gestion-de-shopify-al-siguiente-nivel-con-genai-2bje</guid>
      <description>&lt;p&gt;Tu empresa de venta online recibe muchos pedidos de atención al cliente (Customer Care), y generalmente las preguntas son las mismas siempre, ¿Dónde está mi orden?, ¿Cómo hago una devolución?, Quise aplicar un descuento a mi orden y no funcionó, entre otras, en períodos de muchas ventas y promociones pueden provocar que el equipo de atención al cliente se sature respondiendo emails, contestando llamados telefónicos para justamente responder a estas preguntas para abordar estos temas recurrentes.&lt;/p&gt;

&lt;p&gt;Hoy día existen integraciones telefónicas donde un cliente al llamar tendrá que pasar al menos 3 o 4 minutos presionando los botones de su teléfono para llegar a dar con el estado de su orden o hablar con un represente, o tal vez intentando que un robot entienda lo que quiere decir “en pocas palabras” para terminar derivando con un agente para responder siempre las mismas preguntas.&lt;/p&gt;

&lt;p&gt;Para solucionar esto, construí una solución que utiliza Generative AI  para entender lo que el cliente quiere y armar un agente capaz de responder a las preguntas del cliente utilizando llamadas a una API de GenAI - Amazon Bedrock.&lt;/p&gt;

&lt;p&gt;Si estás dando tus primeros pasos y quieres descubrir cómo aplicar inteligencia artificial a casos de uso de la vida real, si tienes una tienda online y quieres llevar la experiencia de atención al cliente al siguiente nivel, en esta serie de episodios te voy a mostrar cómo utilizando Amazon Bedrock agents y AWS Lambda construí un agente que se encargará de mantener informados a los clientes sobre el estado de sus pedidos realizados en una tienda en Shopify.&lt;/p&gt;

&lt;p&gt;¿Qué vas a aprender?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crear un Agente de Bedrock utilizando uno de los modelos fundacionales disponibles: Claude Instant V1&lt;/li&gt;
&lt;li&gt;Crear una especificación openAPI 3.0 que funcione con un Agente de Bedrock&lt;/li&gt;
&lt;li&gt;Crear una función lambda que cumpla con los requisitos para un agente de Bedrock&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Cómo funciona la aplicación?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Freqjtp315lg9oc11c10f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Freqjtp315lg9oc11c10f.png" alt="Arquitectura de la aplicación" width="659" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La aplicación comprende el backend para que luego la puedas integrar a cualquier cliente de Chat a través de API Gateway o bien mediante llamados a una API.&lt;/p&gt;

&lt;p&gt;Esta aplicación consultará a la &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/agents.html"&gt;API de Bedrock Agents&lt;/a&gt; e interpretará lo que el cliente está solicitando y buscará recolectar toda la información necesaria para poder consultar la información de la orden y entregarla a nuestro cliente.&lt;/p&gt;

&lt;p&gt;Para esto, el agente al tener la información necesaria, invocará una Función Lambda que será la encargada de interactuar con la API de Shopify y devolverle al agente la información que necesita para poder responder la pregunta que el cliente necesita.&lt;/p&gt;

&lt;h2&gt;
  
  
  El  producto final
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/shorts/9pXsVuMylgQ" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ByXWflmS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/9pXsVuMylgQ/hq2.jpg%3Fsqp%3D-oaymwEoCOADEOgC8quKqQMcGADwAQH4AbYIgAKAD4oCDAgAEAEYUiA_KHIwDw%3D%3D%26rs%3DAOn4CLD5ui7yh2BTp-Gwp-V-LFZjCpQkyg" height="360" class="m-0" width="480"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/shorts/9pXsVuMylgQ" rel="noopener noreferrer" class="c-link"&gt;
          Amazon Bedrock Agents Demo - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--zXCfGI7T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.youtube.com/s/desktop/29d8088d/img/favicon.ico" width="16" height="16"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  🤓¿Qué son los Amazon Bedrock Agents?
&lt;/h2&gt;

&lt;p&gt;Los &lt;a href="https://aws.amazon.com/es/bedrock/agents/"&gt;Agentes de Amazon Bedrock&lt;/a&gt; son herramientas de IA que automatizan tareas empresariales, como la gestión de pedidos, mediante instrucciones en lenguaje natural y AWS Lambda, mejorando la eficiencia y reduciendo el trabajo manual.&lt;/p&gt;

&lt;h2&gt;
  
  
  ☑️ Armar un Agente de Bedrock en 4 pasos
&lt;/h2&gt;

&lt;p&gt;Para que el agente funcione vamos a necesitar&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generar credenciales de Shopify: Dado que vamos a utilizar Shopify para este tutorial, es necesario un access Token.&lt;/li&gt;
&lt;li&gt;Escribir una especificación OpenAPI 3.0: Aquí le indicaremos al agente cómo funciona la función, que parámetros recibe y qué respuestas envía y cómo llamarla.&lt;/li&gt;
&lt;li&gt;Creación de una función Lambda que se encargue de obtener el estado de la orden de Shopify.&lt;/li&gt;
&lt;li&gt;Creación y configuración del agente.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔑 Paso 1: Generar las credenciales en Shopify
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.shopify.com"&gt;Shopify&lt;/a&gt; es una plataforma líder de ecommerce que fue creada por desarrolladores y permite realizar la gestión de una tienda online de manera muy sencilla, ha sido pensada y creada por programadores por lo que para cada funcionalidad tiene una API.&lt;/p&gt;

&lt;p&gt;La Función Lambda hace un llamado a una de las API de Shopify, y va a necesitar unas credenciales y permisos para consultar información de los pedidos de la tienda.&lt;/p&gt;

&lt;p&gt;a) Obtener las credenciales, (si ya sabes cómo obtener estas credenciales puedes saltarte esta paso).&lt;br&gt;
b) Crear una aplicación personalizada (Custom App) en Shopify:&lt;br&gt;
Tutorial paso a paso: &lt;a href="https://help.shopify.com/es/manual/apps/app-types/custom-apps#create-and-install-a-custom-app"&gt;https://help.shopify.com/es/manual/apps/app-types/custom-apps#create-and-install-a-custom-app&lt;/a&gt;&lt;br&gt;
c) Definir los permisos que se necesitan: &lt;br&gt;
En este caso el unico necesario es: permiso para leer las ordenes (read_orders) &lt;a href="https://help.shopify.com/es/manual/apps/app-types/custom-apps#get-the-api-credentials-for-a-custom-app"&gt;https://help.shopify.com/es/manual/apps/app-types/custom-apps#get-the-api-credentials-for-a-custom-app &lt;/a&gt;&lt;br&gt;
d) Instalar la app y obtener las credenciales: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2co199xr1glyoan7dsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2co199xr1glyoan7dsw.png" alt="Image description" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zqg0iwu64ynp5xiefr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zqg0iwu64ynp5xiefr9.png" alt="Image description" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  📃 Paso 2: Crear la especificación &lt;a href="https://www.openapis.org/what-is-openapi"&gt;OpenAPI 3.0&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Este es el punto clave y el secreto de la magia, cuanto mejor este especificada y documentada la API, mejor va a funcionar el Agente de Bedrock.&lt;/p&gt;

&lt;p&gt;Una especificación openAPI 3.0 es un archivo de texto json donde con un formato específico se indica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Los endpoints de la API&lt;/li&gt;
&lt;li&gt;Los métodos HTTP que acepta&lt;/li&gt;
&lt;li&gt;Los parámetros que requiere y sus formatos&lt;/li&gt;
&lt;li&gt;La respuesta que va a devolver y sus formatos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para cada uno de estos existe un campo description donde se debe indicar en lenguaje natural que es lo que hace, esto es lo que ayudará al Agente de Bedrock a tomar una decisión&lt;/p&gt;

&lt;p&gt;Cabecera del documento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "openapi": "3.0.0", 
    "info": {
        "title": "Order Info API", 
        "version": "1.0.0",
        "description": "API that provides and identifies order details"
            },
    "paths":{}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Path:&lt;br&gt;
/orders/{orderId}: Recibirá requests GET y va a devolver la información de la orden, para esto indicar que el orderId es un parámetro requerido y se recibe por URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"paths": {
        "/orders/{orderNumber}": {
            "get": {
                "summary": "Gets information about an order",
                "description": "Gets the entire information about an order based on its number",
                "operationId": "getOrderInfo",
                "parameters": [
                    {
                        "name": "orderNumber",
                        "in": "path",
                        "description": "ID of the order that needs to be fetched",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "format": "int64"
                        }
                    }
                ],
                "responses": {}
            }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Respuesta:&lt;/p&gt;

&lt;p&gt;Armar una respuesta formateada de acuerdo a los requerimientos de un agente de Bedrock:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Status Code: 200&lt;/li&gt;
&lt;li&gt;Un objeto con una propiedad content, application/json&lt;/li&gt;
&lt;li&gt;Una enumeración de las propiedades de dicho objeto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crear un objeto con las siguientes propiedades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Id: Numero de la orden&lt;/li&gt;
&lt;li&gt;Status: El estado de la orden&lt;/li&gt;
&lt;li&gt;MoreInfo: Si la orden esta en estado Fulfilled aqui enviaremos la URL para que el cliente pueda hacer el tracking del envío.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aquí una representación del objeto final:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 'application/json': {
            'body': JSON.stringify({
                "id": orderNumber,
                "status": orderStatus,
                "moreInfo": moreInfo
            })
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La especificación openAPI 3.0 de la respuesta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "responses": {
                    "200": {
                        "description": "Object with the order information",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "integer",
                                            "format": "int64"
                                        },
                                        "status": {
                                            "type": "string",
                                            "description": "Status of the order"
                                        },
                                        "moreInfo": {
                                            "type" :"string",
                                            "description": "More information about the order usually the tracking URL"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Especificación openAPI 3.0 completa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "openapi": "3.0.0", 
    "info": {
        "title": "Order Info API", 
        "version": "1.0.0",
        "description": "API that provides and identifies order details"
            },
    "paths": {
        "/orders/{orderNumber}": {
            "get": {
                "summary": "Gets information about an order",
                "description": "Gets the entire information about an order based on its number",
                "operationId": "getOrderInfo",
                "parameters": [
                    {
                        "name": "orderNumber",
                        "in": "path",
                        "description": "ID of the order that needs to be fetched",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "format": "int64"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Object with the order information",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "integer",
                                            "format": "int64"
                                        },
                                        "status": {
                                            "type": "string",
                                            "description": "Status of the order"
                                        },
                                        "moreInfo": {
                                            "type" :"string",
                                            "description": "More information about the order usually the tracking URL"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El archivo final debe ser cargado a un Bucket de S3, será necesario al momento de la creación del Agente.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧑‍💻 Paso 3: Creación de la función Lambda
&lt;/h2&gt;

&lt;p&gt;Crear una  función Lambda que será la encargada de consultar la información de la orden en Shopify, para esto crea una función Lambda: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ingresar a la consola de AWS Lambda &lt;a href="https://console.aws.amazon.com/lambda/home#/functions"&gt;https://console.aws.amazon.com/lambda/home#/functions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Presionar Create Function&lt;/li&gt;
&lt;li&gt;Author from Scratch (Crear desde 0)&lt;/li&gt;
&lt;li&gt;Asignar un nombre&lt;/li&gt;
&lt;li&gt;Elegir el runtime, en este caso el ejemplo lo haré con NodeJS pero puedes hacerlo con el lenguaje de programación que gustes.&lt;/li&gt;
&lt;li&gt;Arquitectura: x86_64 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para hacer consultas a una API Externa por HTTPs se utilizará la librería Axios de NodeJS y en el cuerpo de la función lambda se arma el objeto.&lt;/p&gt;

&lt;p&gt;Si necesitas ayuda sobre cómo utilizar librerías de terceros en NodeJS y Lambda dejame un comentario y escribo un artículo sobre este tema.&lt;/p&gt;

&lt;p&gt;El objeto de Axios necesita 2 propiedades:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;La URL donde vamos a hacer el request&lt;/li&gt;
&lt;li&gt;Los Headers (Cabeceras del request):&lt;/li&gt;
&lt;li&gt;Shopify requiere un Header especial llamado X-Shopify-Access-Token, el mismo sirve para autenticar el request&lt;/li&gt;
&lt;li&gt;El content type del request.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const axios = require('axios');

/** 
Let's create the axios request to Shopify
In order to get the Shopify-Access Token we'll need to create a custom app in Shopify to use the token 
*/
const shopifyRequest = axios.create({
        baseURL: `https://your-shopify-store.myshopify.com/admin/api/2024-01/graphql.json`,
        headers: {
            'X-Shopify-Access-Token': '[AQUI VA EL TOKEN GENERADO]',
            'Content-Type': 'application/json'
        }
    });

exports.handler = async (event) =&amp;gt; {
// Lambda Function Code GOES here

}   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La API de Shopify es GraphQL el siguiente request le indica que recibirá el orderNumber como parámetro, y que queremos traer el fulfillment status de la orden y en caso que haya fulfillments, la información del dicho Fulfillment. (Fulfillment es un objeto que trae información sobre el paquete del cliente cuando el mismo ha sido preparado y enviado)&lt;/p&gt;

&lt;p&gt;A fines didácticos dado que ya se que el orderNumber va a venir en la posición 0 de los parámetros especificamos, esto se puede mejorar buscando la propiedad con el nombre orderNumber dentro del array parameters del objeto event de Lambda.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const orderNumber = event.parameters[0].value;
    const query = `{
        orders(first:1,query: "name:${orderNumber}") {
            edges {
                node {
                    name
                    displayFulfillmentStatus
                    fulfillments {
                        trackingInfo {
                            number
                            url
                        }
                    }
                }
            }
        }
    }`;

    // Let's get the response from Shopify

    const shopifyResponse = await shopifyRequest.post('', { query: query });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el objeto shopifyResponse se guardará la información buscada y responseBody es la respuesta formateada tal como la necesita el Agente de Bedrock&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Let's get the order fulfillment status from the response

    const orderStatus = shopifyResponse.data.data.orders?.edges[0]?.node.displayFulfillmentStatus;
    const moreInfo = shopifyResponse.data.data.orders?.edges[0]?.node.fulfillments[0]?.trackingInfo[0]?.url;
    // Let's return the response

    let responseBody = {
        'application/json': {
            'body': JSON.stringify({
                "id": orderNumber,
                "status": orderStatus,
                "moreInfo": moreInfo
            })
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El Agente de Bedrock necesita recibir en la respuesta algunos atributos para poder continuar con el flujo:&lt;/p&gt;

&lt;p&gt;Como se verá  mås adelante las respuestas de la API van a pertenecer a un ActionGroup del agente, entonces se debe devolver una respuesta para ese ActionGroup específico, el objeto debe tener las siguientes propiedades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El ActionGroup&lt;/li&gt;
&lt;li&gt;El Path&lt;/li&gt;
&lt;li&gt;El Método HTTP que invocó al evento&lt;/li&gt;
&lt;li&gt;El Status Code&lt;/li&gt;
&lt;li&gt;El Body de la respuesta (responseBody)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let actionResponse = {
        actionGroup: event.actionGroup,
        apiPath: event.apiPath,
        httpMethod: event.httpMethod,
        httpStatusCode: 200,
        responseBody: responseBody,

    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego se debe devolver esta actionResponse como respuesta al request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; let response = {
        messageVersion: '1.0',
        statusCode: 200,
        response: actionResponse,
    };
    return response;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repositorio con la función y la especificación OpenAPI: &lt;a href="https://github.com/ricardoceci/aws-bedrock-agents-demo/"&gt;https://github.com/ricardoceci/aws-bedrock-agents-demo/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  👔 Paso 4: Creación de un agente de Bedrock
&lt;/h2&gt;

&lt;p&gt;Lo primero es ir al servicio “Amazon Bedrock”: &lt;a href="https://console.aws.amazon.com/bedrock/"&gt;https://console.aws.amazon.com/bedrock/&lt;/a&gt; y allí seleccionar Agents y luego Create Agent&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrzn8ue6djs7j16238g4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrzn8ue6djs7j16238g4.png" alt="Creación de un Agente de Bedrock" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el siguiente paso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Asignar un nombre al Agente, por ejemplo: OrderInfoAgent&lt;/li&gt;
&lt;li&gt;Indicar si el agente debe solicitar más información en caso que le falte: Si&lt;/li&gt;
&lt;li&gt;Indicar si deseas utilizar un rol ya creado o crear uno nuevo, las opciones de encriptación y el timeout (en cuanto tiempo el agente considera que la sesión terminó) y los tags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A continuación:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seleccionar el FM (Foundational Model) que va a darle vida al agente:
Aquí una guía sobre cómo elegir un modelo fundacional: &lt;a href="https://dev.to/aws-espanol/como-elegir-un-llm-272o"&gt;https://dev.to/aws-espanol/como-elegir-un-llm-272o&lt;/a&gt;
Si no te aparece ninguno es porque debes primero habilitarlos (&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html"&gt;https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Escribir las instrucciones para el agente, aquí es donde es muy importante el prompt que escribas, si bien el modelo puede interpretar múltiples idiomas, escribirlo en inglés hará las cosas más divertidas, por ejemplo: &lt;em&gt;You're a kind customer care agent that is here to provide order status information to our customers, on each response you'll provide as much information as you can grab about the order and you'll always thank our customer for being a loyal customer, if you don't know the answer tell the customer to contact &lt;a href="mailto:customercare@mycompany.com"&gt;customercare@mycompany.com&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokxfh4rt5paigywsc26n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokxfh4rt5paigywsc26n.png" alt="Seleccion de Modelo Fundacional" width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configurar los action groups, un agente puede tener múltiples grupos de acción, que son los que ejecutará en base a lo que el cliente escriba en el chat, en este caso el agente tendrá un solo actiongroup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: GetOrderInformation&lt;/li&gt;
&lt;li&gt;Elegir la lambda function recién creada&lt;/li&gt;
&lt;li&gt;Y la ubicación de la especificación OpenAPI en un bucket S3 que fue creada al principio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7ycogw9pgxh3sh9oogv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7ycogw9pgxh3sh9oogv.png" alt="Configuración de ActionGroup" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Omitir la creación de una base de conocimientos,  en la pantalla de revisión revisar que todo esté correcto y presionar “Create Agent” &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Voilá&lt;/strong&gt;, en unos minutos el agente estará listo para probar:&lt;br&gt;
&lt;strong&gt;Alerta de Spoiler&lt;/strong&gt;: Copiar el ARN que lo será necesario en breve:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuiwyt4pjly8ue4oi5knv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuiwyt4pjly8ue4oi5knv.png" alt="Image description" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💣 Probar el agente:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frodydo72evngjhnfve6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frodydo72evngjhnfve6w.png" alt="Image description" width="356" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explotó!. 🤯&lt;/p&gt;

&lt;p&gt;¿Qué pasó?&lt;br&gt;
Apreció el siguiente error: Access denied while invoking Lambda function &lt;code&gt;arn:aws:lambda:us-east-1:XXXXXXX:function:XXXXXXX. Check the permissions on Lambda function and retry the request&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si presionamos Show trace, no dice nada que ayude, el problema radica en que en ningún momento se le dió permiso al agente para Invocar la Función Lambda.&lt;/p&gt;

&lt;h2&gt;
  
  
  😱 Mi agente de Bedrock no funciona: Permisos necesarios de la Función Lambda
&lt;/h2&gt;

&lt;p&gt;Para que el agente de Bedrock pueda invocar la Función Lambda tiene que tener permisos, para esto hay que agregar una Resouce Based Policy a la Función.&lt;/p&gt;

&lt;p&gt;Desde la consola hacerlo de la siguiente manera:&lt;/p&gt;

&lt;p&gt;1) Dentro de la función lambda, ir a Configurations -&amp;gt; Permissions&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00nsn8vasgz10e1651p0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00nsn8vasgz10e1651p0.png" alt="Lambda Permissions" width="407" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2) En la sección resource based policy statements, presionar “Add Permissions”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flncwgb0qewfzqdope92g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flncwgb0qewfzqdope92g.png" alt="Agregar permisos a una función lambda" width="800" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) Seleccionamos AWS Service, y desplegar la lista de servicios, desafortunadamente, Bedrock no aparece como lista de servicios, así que seleccionar: Other (Otro)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft4uxv6dtmxmahvd5j045.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft4uxv6dtmxmahvd5j045.png" alt="Agregar permisos para Bedrock" width="800" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) Completar la información del Agente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;StatementId: Un identificador para la policy&lt;/li&gt;
&lt;li&gt;Principal: bedrock.amazonaws.com&lt;/li&gt;
&lt;li&gt;Source ARN: El ARN del agente de Bedrock&lt;/li&gt;
&lt;li&gt;Action: lambda:invokeFunction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpekupd254md0ton2z17l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpekupd254md0ton2z17l.png" alt="Información de los permisos" width="800" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎉 Todo funciona 🙂
&lt;/h2&gt;

&lt;p&gt;Ahora al probar el agente y preguntarle sobre el estado de la orden, será capaz de responder con información y no con un error de permisos, el agente está listo.&lt;/p&gt;

&lt;p&gt;El agente además es capaz de hablar en múltiples idiomas dado que el modelo fundacional Claude v1 tiene la capacidad de hacerlo, no todos los modelos tienen esta opción.&lt;/p&gt;

&lt;p&gt;En español:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49bnaofa3b37nza3tlz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49bnaofa3b37nza3tlz3.png" alt="Bedrock Agent en Español" width="353" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En inglés:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzd6dvrgjyz8zuw9le35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzd6dvrgjyz8zuw9le35.png" alt="Bedrock Agent en Inglés" width="269" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Conclusión:
&lt;/h2&gt;

&lt;p&gt;En este episodio has aprendido a crear un Agente de Bedrock en pocos pasos y con muy poco código relacionado a la inteligencia en si del Agente dado que el mismo es capaz de interpretar las necesidades del cliente porque está construido con Generative AI.&lt;/p&gt;

&lt;p&gt;Con este agente se busca reducir la cantidad de llamadas telefónicas o correos electrónicos con preguntas que ya se sabe donde ir a buscar la respuesta o a que endpoints de una API llamar.&lt;/p&gt;

&lt;p&gt;El foco principal de los Agentes de Bedrock es que el desarrollador se ocupe de armar el código que le entregue  la información al Agente y que el Agente sea quien se encargue de:&lt;br&gt;
Entender qué quiere el cliente&lt;br&gt;
Buscar la información, Llamar a una API para realizar una acción.&lt;br&gt;
Entregar la respuesta al cliente.&lt;/p&gt;

&lt;p&gt;También has aprendido a sortear el error sobre el permiso de invocación de la Función Lambda desde un Agente de Bedrock 🙂.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⏭️ Siguientes pasos (Próximo episodio):
&lt;/h2&gt;

&lt;p&gt;El Agente de Bedrock está funcionando, los siguientes pasos son modificar el prompt, mejorar la Función Lambda para que devuelva más información, y  disponibilizar para que sea invocado desde cualquier sitio web, esto lo veremos en el próximo episodio de esta serie 🙂&lt;/p&gt;

</description>
      <category>genai</category>
      <category>bedrock</category>
      <category>shopify</category>
    </item>
    <item>
      <title>AWS Community Builder - ¿Cómo entrar al programa? (Spanish)</title>
      <dc:creator>ricardoceci</dc:creator>
      <pubDate>Tue, 12 Jul 2022 11:20:13 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-community-builder-como-entrar-al-programa-spanish-29d7</link>
      <guid>https://dev.to/aws-builders/aws-community-builder-como-entrar-al-programa-spanish-29d7</guid>
      <description>&lt;p&gt;Si te apasiona el desarrollo o eres curioso, te gusta compartir tus conocimientos y quieres aprender cómo hacerlo de manera profesional, Amazon Web Services creó un programa para estas personas, que es un lujo.&lt;/p&gt;

&lt;p&gt;Soy miembro del programa desde Octubre 2021 y aquí te cuento cómo hice para entrar.&lt;/p&gt;

&lt;p&gt;Desde mis inicios en la programación siempre me apasionó transmitir el conocimiento que iba adquiriendo, y esto lo hacía escribiendo artículos, dictando capacitaciones, y armando comunidades de desarrolladores.&lt;/p&gt;

&lt;p&gt;He organizado la comunidad de Desarrolladores de PHP de Buenos Aires (alla por 2006), luego la de Shopify en Argentina y ahora estoy activamente participando en el AWS Users Group de Buenos Aires (Argentina).&lt;/p&gt;

&lt;p&gt;Personalmente es lo que me apasiona, relacionarme con otros desarrolladores, aprender y compartir conocimiento, estas son las 3 principales características que busca el programa para aceptar a nuevos miembros.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿De qué se trata el programa?
&lt;/h2&gt;

&lt;p&gt;Este programa, además de los swags increibles que recibes, viene acompañado de un grupo en Slack donde tienes contacto directo con gente de AWS, con otros miembros del programa que estan allí para ayudarte en tu carrera.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contacto directo con todos los miembros del programa AWS Heroes&lt;/li&gt;
&lt;li&gt;Charlas exclusivas donde te enseñan a generar contenido, y te cuentan experiencias.&lt;/li&gt;
&lt;li&gt;Oportunidades para dar charlas en distintos grupos de usuarios y eventos de todo el mundo.&lt;/li&gt;
&lt;li&gt;Charlas y capacitaciones de acceso anticipado a nuevas features que AWS esta por lanzar al mercado.&lt;/li&gt;
&lt;li&gt;USD 500 de crédito de AWS&lt;/li&gt;
&lt;li&gt;1 año de acceso a CloudAcademy&lt;/li&gt;
&lt;li&gt;1 Voucher de certificación gratis por año&lt;/li&gt;
&lt;li&gt;Posibilidad de publicar en dev.to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todo el tiempo se van agregando beneficios&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cuál es el criterio de aceptación?
&lt;/h2&gt;

&lt;p&gt;No hay un criterio de aceptación específico, pero si dejame decirte que todo aquel entusiasta por el desarrollo de comunidades, generación de contenido y que tenga pasión por lo que hace y pueda demostrarlo, es muy bienvenido al programa.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué pasa si no me aceptan?
&lt;/h2&gt;

&lt;p&gt;Un tropezón no es caída, el que no te acepten no significa que no puedas volver a anotarte en el próximo período, el que no te acepten te tiene que dar más fuerzas para continuar generando contenido e involucrándote y mejorando tu presentacíon / aplicación para la próxima apertura.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Tengo que tener contenido publicado?
&lt;/h2&gt;

&lt;p&gt;El programa esta pensado para todos aquellas personas que deseen potenciar sus habilidades en la generación de contenido, dictado de charlas, transmisión de conocimientos y el networking entre desarrolladores.&lt;/p&gt;

&lt;p&gt;Todo aquello que hayas hecho para potenciar las comunidades en el pasado ayudan, y te van a ayudar en el proceso de aplicación al programa.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Tengo que hablar inglés?
&lt;/h2&gt;

&lt;p&gt;El programa esta abierto a cualquier persona del mundo, y se aconseja que personas de las comunidades menos representadas se inscriban (Latinos, Hispanos, entre otros).&lt;/p&gt;

&lt;p&gt;Puedes no hablar inglés, pero un conocimiento mínimo es requerido, y si quieres aprovechar al máximo todas las charlas, debes saber algo, dado que la mayoría de las charlas están en este idioma.&lt;/p&gt;

&lt;p&gt;El formulario de inscripción está en inglés, luego puedes desarrollar tu contenido en Español si gustas (yo lo hago).&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Tengo que ser un experto en el tema?
&lt;/h2&gt;

&lt;p&gt;La respuesta corta es &lt;strong&gt;no&lt;/strong&gt;, como mencionaba anteriormente, es importante que si tengas ganas de compartir contenido y tus conocimientos, de involucrarte con las comunidades y hacer crecer el ecosistema de desarrolladores, este es tu lugar.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cómo me inscribo?
&lt;/h2&gt;

&lt;p&gt;Las inscripciones abren dos veces por año y se hacen desde el siguiente sitio web:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/es/developer/community/community-builders/" rel="noopener noreferrer"&gt;https://aws.amazon.com/es/developer/community/community-builders/&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
Las inscripciones a la fecha de escritura de este artículo están abiertas hasta el 17 de Julio de 2022 a la media noche, hora del pacífico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Swag de bienvenida
&lt;/h2&gt;

&lt;p&gt;Si todavía no te decidiste, aquí una ayuda más:&lt;/p&gt;

&lt;p&gt;¿A quién no le gustan los regalos?….&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7fftqf6aivz5r7uc4k8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7fftqf6aivz5r7uc4k8.jpg" alt="Welcome Kit AWS Community Builders" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awscommunity</category>
      <category>communitybuilders</category>
    </item>
    <item>
      <title>Crear un recomendador de productos con Amazon Personalize (Spanish)</title>
      <dc:creator>ricardoceci</dc:creator>
      <pubDate>Thu, 23 Jun 2022 11:31:55 +0000</pubDate>
      <link>https://dev.to/aws-builders/crear-un-recomendador-de-productos-con-amazon-personalize-spanish-1fi3</link>
      <guid>https://dev.to/aws-builders/crear-un-recomendador-de-productos-con-amazon-personalize-spanish-1fi3</guid>
      <description>&lt;p&gt;Esta vez investigando alguna herramienta para recomendación de productos en mi trabajo, me encontré con Personalize (Amazon Personalize), poderosa pero ¿Simple?. Veamos!&lt;/p&gt;

&lt;p&gt;A continuación una guía de cómo dar tus primeros pasos.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es Amazon Personalize?
&lt;/h2&gt;

&lt;p&gt;Según AWS&lt;br&gt;
Amazon Personalize es un servicio administrado (fully managed) de Machine Learning que hace “fácil” a los desarrolladores presentar experiencias personalizadas a sus usuarios, y refleja el conocimiento y la experiencia que tiene Amazon al momento de construir sistemas de personalización.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/personalize/latest/dg/what-is-personalize.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/personalize/latest/dg/what-is-personalize.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  El producto final
&lt;/h2&gt;

&lt;p&gt;El objetivo de esta guía es que puedas conocer los fundamentos de Amazon Personalize, el resultado final será una recomendación de productos específicos para cada uno de los clientes de nuestro sitio.&lt;/p&gt;
&lt;h2&gt;
  
  
  Materiales
&lt;/h2&gt;

&lt;p&gt;En este caso nos vamos a focalizar en generar un “recommender”para recomendar productos a nuestros usuarios&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tiempo requerido para este laboratorio: 1 – 2 horas.&lt;/li&gt;
&lt;li&gt;Una cuenta de AWS (Si no tienes cuenta, debes crear una: &lt;a href="(https://portal.aws.amazon.com/billing/signup#/start/email)"&gt;https://portal.aws.amazon.com/billing/signup#/start/email&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Lo que vamos a utilizar cuesta aproximadamente aprox USD 2 si ya no tienes free tier disponible.&lt;/li&gt;
&lt;li&gt;Un bucket de S3 para poder subir los archivos de datos.
Datasets (archivos CSV con información)&lt;/li&gt;
&lt;li&gt;Nivel Padawan (aprendiz): Interacciones de los usuarios con tus productos&lt;/li&gt;
&lt;li&gt;Nivel Jedi (Intermedio): Interacciones + Productos con atributos&lt;/li&gt;
&lt;li&gt;Nivel Yoda (Avanzado): Interacciones + Productos con atributos + Usuarios&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Preparación
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Creación del Bucket de S3
&lt;/h3&gt;

&lt;p&gt;(si ya tienes un bucket de S3 para guardar información, pasa a la sección de configuración adicional del bucket para Amazon Personalize)&lt;/p&gt;

&lt;p&gt;En la consola de AWS buscamos S3 en el buscador de servicios que se presenta arriba a la izquierda.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50jaxw5l0e6cz9m8liyh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50jaxw5l0e6cz9m8liyh.png" alt="Buscar S3 en la consola de AWS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luego vamos a “Buckets” – Create Bucket&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrly1pen5nzjktsd1arb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrly1pen5nzjktsd1arb.png" alt="Ir a Buckets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elegimos un nombre representativo para el Bucket:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finwo3njodw5pqlzdkk7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finwo3njodw5pqlzdkk7y.png" alt="Definir el nombre del bucket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A los fines de este paso a paso dejamos los valores del formulario por defecto, pero sugiero en caso de quere pasar a producción el trabajo evaluar si hay algún requisito adicional necesario en lo que respecta a copia de seguridad, versionado y cifrado de la información.&lt;/p&gt;

&lt;p&gt;Presionamos: Crear Bucket&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nt9wlm7ki6t3z58h0mj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nt9wlm7ki6t3z58h0mj.png" alt="Crear Bucket"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuración adicional del Bucket para Amazon Personalize
&lt;/h3&gt;

&lt;p&gt;Es requerido que el Bucket de S3 permita el acceso desde el servicio de Amazon Personalize para poder leer los archivos que hay dentro del bucket.&lt;/p&gt;

&lt;p&gt;Desde el listado de Buckets clickeamos sobre el bucket recién creado&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsf1mn6si3wg2w0rm33db.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsf1mn6si3wg2w0rm33db.png" alt="Acceder al bucket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la siguiente pantalla nos vamos a donde dice “Permisos”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuz47xo8enb5alf7w5q95.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuz47xo8enb5alf7w5q95.png" alt="Sección Permisos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la sección Política del bucket, clickeamos “Editar”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb0diobd90f3erz682vb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb0diobd90f3erz682vb.png" alt="Política del Bucket (Bucket Policy)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Allí, en caso de ser este un bucket nuevo, eliminamos el valor por defecto y copiamos y pegamos el siguiente JSON reemplazando bucket-name por el nombre de nuestro bucket.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Si no es un bucket nuevo y tiene alguna politica adjunta, agregar los permisos requeridos (Effect, Pricipal, Action y Resource) a la política actual.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
    "Version": "2012-10-17",&lt;br&gt;
    "Id": "PersonalizeS3BucketAccessPolicy",&lt;br&gt;
    "Statement": [&lt;br&gt;
        {&lt;br&gt;
            "Sid": "PersonalizeS3BucketAccessPolicy",&lt;br&gt;
            "Effect": "Allow",&lt;br&gt;
            "Principal": {&lt;br&gt;
                "Service": "personalize.amazonaws.com"&lt;br&gt;
            },&lt;br&gt;
            "Action": [&lt;br&gt;
                "s3:GetObject",&lt;br&gt;
                "s3:ListBucket"&lt;br&gt;
            ],&lt;br&gt;
            "Resource": [&lt;br&gt;
                "arn:aws:s3:::bucket-name",&lt;br&gt;
                "arn:aws:s3:::bucket-name/*"&lt;br&gt;
            ]&lt;br&gt;
        }&lt;br&gt;
    ]&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Deberá quedar así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ybtmn1ny5hoebnjk9lz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ybtmn1ny5hoebnjk9lz.png" alt="Ejemplo de Bucket Policy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparar los archivos de datos: (Datasets)
&lt;/h2&gt;

&lt;p&gt;Asegúrate de tener archivos CSV preparados con las siguientes estructuras&lt;/p&gt;

&lt;h3&gt;
  
  
  Interacciones
&lt;/h3&gt;

&lt;p&gt;Es recomendable que este CSV tenga al menos 1000 registros del tipo “View” para sacar provecho de las diferentes “recetas”que hay para recomendar productos.&lt;/p&gt;

&lt;p&gt;Es importante que aquí haya eventos solo “Positivos” Amazon Personalize no reconoce eventos “Negativos”, ejemplo: Eliminar un producto del carrito, para Amazon Personalize no es significativo.&lt;/p&gt;

&lt;p&gt;Los eventos que AWS Personalize indica que debemos registrar son los: View y los Purchase&lt;/p&gt;

&lt;p&gt;Es importante respetar el nombre de las columnas requeridas y opcionales.&lt;/p&gt;

&lt;p&gt;Se pueden agregar hasta 5 columnas adicionales de metadata que combinadas con los diferent event types no superen las 10 columnas respetando los formatos establecidos: &lt;a href="https://docs.aws.amazon.com/personalize/latest/dg/how-it-works-dataset-schema.html#personalize-datatypes" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/personalize/latest/dg/how-it-works-dataset-schema.html#personalize-datatypes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si alguna de las columnas es del tipo CATEGORICAL y contiene más de un valor, separar las columnas con pipes “|”&lt;/p&gt;

&lt;h4&gt;
  
  
  Columnas Requeridas
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;USER_ID (string)&lt;/li&gt;
&lt;li&gt;ITEM_ID (string)&lt;/li&gt;
&lt;li&gt;TIMESTAMP (long)&lt;/li&gt;
&lt;li&gt;EVENT_TYPE (string, (Purchase, View))&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Columnas Opcionales
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;EVENT_VALUE (float), por si queremos darle más peso a un evento&lt;/li&gt;
&lt;li&gt;IMPRESSION (string), aca podemos pasar que conjunto de productos se presentaron al usuario cuando interactuó con el producto que estamos enviando (Más info: &lt;a href="https://docs.aws.amazon.com/personalize/latest/dg/interactions-datasets.html#interactions-impressions-data" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/personalize/latest/dg/interactions-datasets.html#interactions-impressions-data&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;RECOMMENDATION_ID (string)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Items (Productos con atributos)
&lt;/h3&gt;

&lt;p&gt;Este dataset es opcional, pero te lo recomiendo si queres obtener recomendaciones más acordes a tus usuarios.&lt;/p&gt;

&lt;h4&gt;
  
  
  Columnas Requeridas
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;ITEM_ID (string)&lt;/li&gt;
&lt;li&gt;PRICE (float)&lt;/li&gt;
&lt;li&gt;CATEGORY_L1&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Columnas Opcionales
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;CATEGORY_L2 (string)&lt;/li&gt;
&lt;li&gt;CATEGORY_L3 (string)&lt;/li&gt;
&lt;li&gt;PRODUCT_DESCRIPTION (textual)&lt;/li&gt;
&lt;li&gt;CREATION_TIMESTAMP (float)&lt;/li&gt;
&lt;li&gt;AGE_GROUP (categorical, string)&lt;/li&gt;
&lt;li&gt;ADULT (categorical, string): Yes, No&lt;/li&gt;
&lt;li&gt;GENDER (categorical, string): Male, Female, Unisex&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Usuarios
&lt;/h3&gt;

&lt;p&gt;Este dataset también es opcional, pero como mencione anteriormente, cuanto más especificas quieras las recomendaciones y más información le des al sistema, mejor.&lt;/p&gt;

&lt;p&gt;En este dataset debemos volcar la información que nos parezca relevante de los usuarios, el ID, si tenemos algún loyalty program el nivel en el que se encuentran (Bronze, Gold, Platinum, Diamond, o el nombre que le hayamos dado), la edad, género, o por ejemplo que tipos de series le gustan.&lt;/p&gt;

&lt;h4&gt;
  
  
  Columnas Requeridas
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;USER_ID&lt;/li&gt;
&lt;li&gt;Algun metafield (Ejemplo Loyalty_program, age, gender)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Subir los Datasets al Bucket de S3
&lt;/h2&gt;

&lt;p&gt;Estos 3 Datasets (recuerda que el único obligatorio es el de interactions) los debemos subir al Bucket de S3 creado al principio.&lt;/p&gt;

&lt;p&gt;Dentro del Bucket presionamos: Cargar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkuet8y1x1uvn8tlgoav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkuet8y1x1uvn8tlgoav.png" alt="Agregar archivos al bucket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agregar Archivos&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjas23v410td913u6few.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjas23v410td913u6few.png" alt="Cargar archivos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luego elegimos en nuestra carpeta local los archivos que queremos subir y presionamos “Cargar”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhmiy3c90801csltomk5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhmiy3c90801csltomk5.png" alt="Cargar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez terminada la carga, presionamos “Cerrar”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnrmdr0nmvqq6yrrgf1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnrmdr0nmvqq6yrrgf1y.png" alt="Cerrar la ventana"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso a paso
&lt;/h2&gt;

&lt;p&gt;Suponiendo que ya tienes los datasets creados, los pasos a seguir son los siguientes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;En la consola de AWS buscamos Amazon Personalize&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n2fhtlgz2jtia7nm67y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n2fhtlgz2jtia7nm67y.png" alt="Buscar Amazon Personalize en el dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Crear Dataset Group
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Dentro de Amazon Personalize nos vamos a donde dice Create Dataset Group&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyfgqd0zhqnbaodtvtiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyfgqd0zhqnbaodtvtiw.png" alt="Crear Dataset Group"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Un datasetgroup es un “Agrupador de información”, aquí es donde agruparemos los distintos contenidos para recomendar, por ejemplo podemos tener un dataset group para recomendar libros, otro para recomendar videos, otro para recomendar ropa.&lt;/p&gt;

&lt;p&gt;Le asignamos un nombre, y en seleccionamos el tipo de “Dominio” para los casos de uso, en este caso vamos a seleccionar Ecommerce, dado que estamos buscando recomendar productos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnj3u3mvbly255kit6sog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnj3u3mvbly255kit6sog.png" alt="Asignar un nombre y elegir un dominio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Crear el primer dataset en Amazon Personalize
&lt;/h2&gt;

&lt;p&gt;Ahora crearemos nuestro primer dataset, en este caso el de interacciones, un dataset es justamente la información que vamos a cargar, le ponemos un nombre al dataset de interacciones y un nombre al schema.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9dxlm8ej092f3cux4xr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9dxlm8ej092f3cux4xr.png" alt="Crear Dataset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Definir el Schema
&lt;/h2&gt;

&lt;p&gt;En este caso podemos dejar el schema por defecto dado que es el que vamos a estar utilizando en nuestro sistema, pero si gustamos debemos hacer las modificaciones que deseemos aqui.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqarpu5oxa8kgku8y2w29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqarpu5oxa8kgku8y2w29.png" alt="Definir el Schema"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tipos de datos para los Schemas
&lt;/h2&gt;

&lt;p&gt;Esta es una lista de los diferentes tipos soportados por AWS Personalize para los schemas:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tipo&lt;/th&gt;
&lt;th&gt;JSON&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;{"name":"Valor","type":"float",}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;double&lt;/td&gt;
&lt;td&gt;{"name":"Price","type":"double",}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;{"name":"Quantity","type":"int",}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;td&gt;{"name":"Valor_Preciso","type":"long",}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;{"name":"ITEM_ID","type":"string",}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean (true o false)&lt;/td&gt;
&lt;td&gt;{"name":"LIKES_FRUIT","type":boolean,}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null (Si queremos indicar que algun valor puede ser nulo, debemos incluirlo al momento de la definición)&lt;/td&gt;
&lt;td&gt;{"name":"GENRES","type":["null","string"]"categorical":true}&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cuando un campo es del tipo Categorical, debe aclararse al momento de definir el schema (en el caso del dataset de interactions, no tenemos ningun tipo categorical, pero probablemente en el dataset de usuarios o productos lo tendremos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
"name":"GENRES",
"type":"string",
"categorical":true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Importar el Dataset (Crear un import job) en Amazon Personalize
&lt;/h2&gt;

&lt;p&gt;El paso siguiente es importar los datos, para esto Personalize nos solicita crear un import job, cada vez que querramos importar nuevos datos, debemos crear un Import Job.&lt;/p&gt;

&lt;p&gt;Aquí le definimos un nombre a nuestro import job y escribimos la ubicación del archivo CSV con las interacciones de los usuarios. Recuerda que el Bucket tiene que tener la policy que creamos en el apartado “Preparación”, sino no va a funcionar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqxm6hmuwlmap8rssoc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqxm6hmuwlmap8rssoc0.png" alt="Crear el Import Job"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A continuación nos solicita que le indiquemos cuál es el Rol que puede acceder a el bucket de S3 creado anteriormente, este rol debe tener la política AmazonPersonalizeFullAccess.&lt;/p&gt;

&lt;p&gt;En mi caso no tengo este rol creado, por lo que voy a elegir ‘Create a new role’ y Amazon Personalize lo hará por mí.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshue4gj8nyj4l22l35op.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshue4gj8nyj4l22l35op.png" alt="Crear un rol"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luego indicamos a que Bucket / Buckets tendrá acceso este rol.&lt;/p&gt;

&lt;p&gt;Podemos escribir el nombre de nuestro Bucket, en mi caso es redundante dado que el Bucket ya contiene el nombre personalize dentro de él (rc-personalize-datos), por ende al utilizar el wizard de AWS está creando un rol para todos los buckets que contengan el nombre Personalize.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfp3cmfcxb4fg0z8i2r2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfp3cmfcxb4fg0z8i2r2.png" alt="Definir reglas para el rol"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Presionamos Create Role y ya tendremos nuestro Rol creado.&lt;/p&gt;

&lt;p&gt;En la ventana original presionamos: Create dataset import job&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzmuvrdnb8ptv115w19vo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzmuvrdnb8ptv115w19vo.png" alt="Presionar crear"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si todo sale bien, comenzara la importación del dataset.&lt;/p&gt;

&lt;p&gt;Si clickeamos en “Overview” dentro de Amazon Personalize, podremos observar que la importación del dataset de interactions está en curso, en mi caso fueron 250Mb de datos, y tardó en procesarse aproximadamente 3 minutos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj649qb9g8z1zxv95ihzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj649qb9g8z1zxv95ihzc.png" alt="Ventana de Overview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Crear el Recomendador
&lt;/h2&gt;

&lt;p&gt;Una vez que ya nos aparece “Active” el dataset de interactions, se nos habilita el siguiente paso para comenzar a crear los “Recommenders”, en la pantalla de Overview presionamos “Create Recommenders”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3haudm0hzaina71h5zc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3haudm0hzaina71h5zc.png" alt="Crear Recommender"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aquí AWS Personalize nos muestra las diferentes opciones de recomendadores que podemos crear (son las recetas/casos de uso), aquí debemos tener especial cuidado con las recetas que utilizamos dado que se nos cobrará por cada receta que decidamos crear y cada recomendador activo que tengamos. (Ver Explicación de Precios)&lt;/p&gt;

&lt;p&gt;En nuestro caso vamos a elegir el caso de uso: Recommended for you&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7c089ov0t0ea2eylwbvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7c089ov0t0ea2eylwbvt.png" alt="Selección del caso de uso Recommended for you"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aquí un detalle de los casos de uso:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Caso de uso&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Customers who viewed X also viewed&lt;/td&gt;
&lt;td&gt;Item ID&lt;/td&gt;
&lt;td&gt;Listado de items que otros customers vieron luego de ver el que pasamos como input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frequently Bought Together&lt;/td&gt;
&lt;td&gt;Item ID&lt;/td&gt;
&lt;td&gt;Listado de items que otros customers frecuentemente compraron junto a este.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best Sellers&lt;/td&gt;
&lt;td&gt;User_ID&lt;/td&gt;
&lt;td&gt;De acuerdo a los items que compró el usuario devuelve un listado de otros items que mejor se vendieron&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Most Viewed&lt;/td&gt;
&lt;td&gt;User_ID&lt;/td&gt;
&lt;td&gt;Basado en las veces que el Customer vio un item, trae items recomendados para ver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recommended for you&lt;/td&gt;
&lt;td&gt;User_ID&lt;/td&gt;
&lt;td&gt;Devuelve items que son recomendados para el usuario.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Amazon Personalize luego nos da la opción de configurar de manera avanzada este recomendador (o los que hayamos seleccionado)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6akom52wp17msejndgy8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6akom52wp17msejndgy8.png" alt="Configuración Avanzada del Recomendador"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En este caso:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimum recommendation requests per second&lt;/strong&gt;: Este parámetro es muy importante dado que aqui debemos especificar cuantas veces por segundo vamos a utilizar el recomendador y amazon nos cobra por la cantida de horas/recomendaciones generadas, si nos excedemos de esta cantidad, Amazon Personalize auto escalará para poder satisfacer los requests, y luego cuando la demanda baje, volverá a lo que configuremos aquí, pero nunca menos.&lt;/p&gt;

&lt;p&gt;En este caso podremos realizar un request por segundo, lo que nos indica 60 requests por minuto, son 3.600 requests por hora. Recomiendo dejarlo en 1 si no sabemos la cantidad de requests minimos e ir ajustando este parámetro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Emphasis on exploring less relevent items&lt;/strong&gt;: El sistema para poder recomendar generalmente empieza con los items con mayores interacciones, dado que asume que estos son los más claros, pero también se sugiere dejar un margen para “Explorar”, aqui es un valor que va de 0 a 1, en este caso por ejemplo 0.3 significa que el 30% de los items recomendados podrán ser exploratorios, es deecir que se usarán para experimentar. (Supongamos que recomendamos de a 4 items, 1.2 items podrian ser exploratorios). (Para que esto funcione bien, se recomienda subir un dataset de interactions nuevo periódicamente, o utilizar un Event Tracker. (&lt;a href="https://docs.aws.amazon.com/personalize/latest/dg/recording-events.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/personalize/latest/dg/recording-events.html&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exploration item age cut off&lt;/strong&gt;: En caso que deseemos explorar, lo que va a hacer el sistema es no utilizar para las recomendaciones items que no hayan tenido interacciones en los últimos días especificados en este parámetro, en nuestro caso no recomendará items que no hayan tenido interacciones en los últimos 30 días.&lt;/p&gt;

&lt;p&gt;Presionamos: Create Recommenders&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F820cc1v7t37zooen3q8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F820cc1v7t37zooen3q8b.png" alt="Crear Recommender"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El Recommender pasará a crearse, este proceso demora varios minutos, en mi caso duró 60 minutos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsqq0yu73rm5ug3jnc03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsqq0yu73rm5ug3jnc03.png" alt="Creación de recommender en proceso"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluando el recomendador creado
&lt;/h2&gt;

&lt;p&gt;Hay dos maneras de evaluar las recomendaciones de Amazon Personalize, una y la más recomendable es la denominada “online”, es aquella que se mide en base a los clicks que hicieron los usuarios a los productos recomendados por Amazon Personalize.&lt;/p&gt;

&lt;p&gt;La segunda, es en base a las métricas que arroja Amazon Personalize al momento de crear el recomendador.&lt;/p&gt;

&lt;p&gt;Una vez finalizada la creación del Recommender, vemos que nos devuelve métricas en base a lo que pudo entrenar el sistema y las recomendaciones que arrojará.&lt;/p&gt;

&lt;p&gt;Estas métricas se generan de la siguiente manera:&lt;/p&gt;

&lt;p&gt;El sistema toma el 10% como muestra para testeo.&lt;/p&gt;

&lt;p&gt;Se utiliza el dataset para entrenar el modelo.&lt;/p&gt;

&lt;p&gt;Luego se le pasa el 90% de la data más vieja como parámetro al modelo y trata de predecir el 10% que luego es comparado con la data de testeo.&lt;/p&gt;

&lt;p&gt;A modo de resumen estos valores van de 0 a 1, cuando más cerca del 1, mejor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu8um01dzzray9xez0x24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu8um01dzzray9xez0x24.png" alt="Métricas para evaluar el recomendador"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Métrica&lt;/th&gt;
&lt;th&gt;Descripción&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Coverage&lt;/td&gt;
&lt;td&gt;Cuántos items diferentes recomienda el sistema sin entrar a repetir el mismo item. Si utilizamos exploración es probable que este número sea más alto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean Reciprocal Rank at 25&lt;/td&gt;
&lt;td&gt;Esta medida nos sirve para evaluar la precisión del recomendador para acertar el Top 1 recomendado.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Normalized Discounted Cumulative Gain at (5,10,25)&lt;/td&gt;
&lt;td&gt;Este valor nos indica para el Top 5,10,25 el grado de relevancia de los resultados, penalizando los resultados que el sistema consideró relevantes pero en el testing aparecieron en ubicaciones más abajo, es decir aqui se premian los resultados relevantes que aparecieron arriba en las listas.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Precision at 5,10,25&lt;/td&gt;
&lt;td&gt;Esta métrica nos indica la relevancia de los resultados en un Top 5,10 y 25, en este caso en vez de considerar la relevancia de los resultados, se considera la precisión de la recomendacion de los elementos relevantes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Probando el recomendador
&lt;/h2&gt;

&lt;p&gt;En la pantalla principal del recomendador nos vamos a “Test Recommender”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6m1kck6x1pe5lntxbc3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6m1kck6x1pe5lntxbc3m.png" alt="Probar recomendador"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luego nos solicitará ingresar el parámetro User ID:&lt;/p&gt;

&lt;p&gt;Ingresamos algun usuario de nuestra base de datos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feq5sceg2v94sdla7dcn6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feq5sceg2v94sdla7dcn6.png" alt="Ingresar parámetros requeridos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A continuacion nos mostrará 25 recomendaciones para este usuario:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jjw06v8j3e1ssak3kfh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jjw06v8j3e1ssak3kfh.png" alt="Resultados del recomendador"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Cómo seguir?&lt;/p&gt;

&lt;p&gt;A continuación queda a nuestro criterio como continuar, por ejemplo podemos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crear un script en nuestro lenguaje de programación favorito que consulte la API de Recomendaciones&lt;/li&gt;
&lt;li&gt;Utilizar recomendaciones en Batch para crear campañas específicas&lt;/li&gt;
&lt;li&gt;Implementar un Event Tracker para ir optimizando el recomendador&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Explicación de los costos
&lt;/h2&gt;

&lt;p&gt;Los precios se encuentran en el siguiente link: &lt;a href="https://aws.amazon.com/es/personalize/pricing/" rel="noopener noreferrer"&gt;https://aws.amazon.com/es/personalize/pricing/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dado que a veces cuesta entender el pricing, voy a tratar de hacerlo más sencillo&lt;/p&gt;

&lt;p&gt;Amazon cobra por:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ingesta de datos (proceso de los datasets + store de los datasets en S3)&lt;/li&gt;
&lt;li&gt;Por hora que el recommender esté ejecutandose y cada 100.000 usuarios (hasta 4000 recomendaciones por hora) y escalando en recomendaciones por hora en base a la cantidad de usuarios. (un usuario es un USER_ID dentro del dataset de interacciones y de usuarios).&lt;/li&gt;
&lt;li&gt;Si excedemos las 4000 recomendaciones por hora (o las que vengan incluidas en cada hora de recommender), por cada 1.000 se cobran valores adicionales (ej. $0.0833 a hoy para 1000 recomendaciones para 100.000 usuarios)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Recomendaciones finales
&lt;/h2&gt;

&lt;p&gt;Para no incurrir en costos inesperados:&lt;/p&gt;

&lt;p&gt;Una vez finalizado el ejercicio mencionado en este artículo&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recuerda borrar los archivos de datos subidos y eliminar el Bucket de S3&lt;/li&gt;
&lt;li&gt;Elimina los recommenders que no uses como sus datgaset groups y sus datasets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;En caso que desees pausar y continuar en otro momento, te recomiendo presionar el botón “Stop recommender” que pausara el billing y el entrenamiento del Recommender hasta que vuelvas lo reactives.&lt;/p&gt;

&lt;p&gt;Una vez detenido para reactivarlo hay que ingresar al recommender y presionar “Start Recommender”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7g7jkuf01f8n5e1eblik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7g7jkuf01f8n5e1eblik.png" alt="Stop / Start Recommender"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>personalize</category>
    </item>
  </channel>
</rss>
