{"id":1978,"date":"2025-02-21T07:02:27","date_gmt":"2025-02-21T07:02:27","guid":{"rendered":"https:\/\/mailitics.com\/index.php\/2025\/02\/21\/ai-agents-from-zero-to-hero-part-1\/"},"modified":"2025-02-21T07:02:27","modified_gmt":"2025-02-21T07:02:27","slug":"ai-agents-from-zero-to-hero-part-1","status":"publish","type":"post","link":"https:\/\/mailitics.com\/index.php\/2025\/02\/21\/ai-agents-from-zero-to-hero-part-1\/","title":{"rendered":"AI Agents from Zero to Hero \u2013 Part 1"},"content":{"rendered":"<p>    AI Agents from Zero to Hero \u2013 Part 1<br \/>\n \t<BR><br \/>\n<BR><\/BR><br \/>\n    <!-- no image --><br \/>\n \t<BR><br \/>\n<BR><\/BR><\/p>\n<div>\n<h2 class=\"wp-block-heading\"><strong>Intro<\/strong><\/h2>\n<p class=\"wp-block-paragraph\"><strong>AI Agents<\/strong> are autonomous programs that perform tasks, make decisions, and communicate with others. Normally, they use a set of tools to help complete tasks. In GenAI applications, these Agents process sequential reasoning and can use external tools (like web searches or database queries) when the LLM knowledge isn\u2019t enough. Unlike a basic chatbot, which generates random text when uncertain, an AI Agent activates tools to provide more accurate, specific responses.<\/p>\n<p class=\"wp-block-paragraph\">We are moving closer and closer to the concept of <strong><a href=\"https:\/\/towardsdatascience.com\/tag\/agentic-ai\/\" title=\"Agentic Ai\">Agentic Ai<\/a>:<\/strong> systems that exhibit a higher level of autonomy and decision-making ability, without direct human intervention. While today\u2019s AI Agents respond reactively to human inputs, tomorrow\u2019s Agentic AIs proactively engage in problem-solving and can adjust their behavior based on the situation.<\/p>\n<p class=\"wp-block-paragraph\">Today, building Agents from scratch is becoming as easy as training a logistic regression model 10 years ago. Back then, <em>Scikit-Learn<\/em> provided a straightforward library to quickly train Machine Learning models with just a few lines of code, abstracting away much of the underlying complexity.<\/p>\n<p class=\"wp-block-paragraph\">In this tutorial, I\u2019m going to show how to <strong>build from scratch different types of AI Agents<\/strong>, from simple to more advanced systems. I will present some useful Python code that can be easily applied in other similar cases (just copy, paste, run) and walk through every line of code with comments so that you can replicate this example.<\/p>\n<h2 class=\"wp-block-heading\"><strong>Setup<\/strong><\/h2>\n<p class=\"wp-block-paragraph\">As I said, anyone can have a custom Agent running locally for free without GPUs or API keys. The only necessary library is <a href=\"https:\/\/ollama.com\/\"><strong><em>Ollama<\/em><\/strong><\/a><strong><em> <\/em><\/strong>(pip install ollama==0.4.7), as it allows users to run LLMs locally, without needing cloud-based services, giving more control over data privacy and performance.<\/p>\n<p class=\"wp-block-paragraph\">First of all, you need to download <em><a href=\"https:\/\/towardsdatascience.com\/tag\/ollama\/\" title=\"Ollama\">Ollama<\/a><\/em> from the website.\u00a0<\/p>\n<figure class=\"wp-block-image alignwide\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXdqND8TKZT560gYrNhR6I6ZliY-O010UjLprMi7V6N53yGh82KZkvZiVaITs3kM6xWz4K6mkEFWMtwpMIFSPUM6kIGHOQd2MWMhbfvCXMXPElATIodyWx3XygAX8FPjs33HJHXcxw?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<p class=\"wp-block-paragraph\">Then, on the prompt shell of your laptop, use the command to download the selected LLM. I\u2019m going with Alibaba\u2019s <strong><em>Qwen<\/em><\/strong>, as it\u2019s both smart and lite.<\/p>\n<figure class=\"wp-block-image alignwide\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXflHQgmPh_BWiFyQuXmofN9tmRyvx7xgx0wIrT2VAX_6VTsLIrwl7rsddltiQisQov2GvvF3KwLV4NZzBuYhgvDEhWVedHOGdRZ7roxj1rKQohYpG2FFHZc6hYWfihSm7wvz4XG?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<p class=\"wp-block-paragraph\">After the download is completed, you can move on to Python and start writing code.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">import ollama\nllm = \"qwen2.5\"<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Let\u2019s test the LLM:<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">stream = ollama.generate(model=llm, prompt='''what time is it?''', stream=True)\nfor chunk in stream:\n    print(chunk['response'], end='', flush=True)<\/code><\/pre>\n<figure class=\"wp-block-image alignwide\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXevGNunmTe5DXUXgPPKsPNA1ueM7aFywipZIWuMRw0SwO8iVcScGEt3cZaitee5SPiPhCU3TJy3iMvf1evCeaEZCbSI8lsKG25fcMDo5OCB4mXNMLIZBEKcnAq4so7EwMn4_njQrw?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<p class=\"wp-block-paragraph\">Obviously, the LLM per se is very limited and it can\u2019t do much besides chatting. Therefore, we need to provide it the possibility to take action, or in other words, to <strong>activate Tools<\/strong>.<\/p>\n<p class=\"wp-block-paragraph\">One of the most common tools is the ability to <strong>search the Internet<\/strong>. In Python, the easiest way to do it is with the famous private browser <a href=\"https:\/\/pypi.org\/project\/duckduckgo-search\/\"><em>DuckDuckGo<\/em><\/a><em> <\/em>(<code>pip install duckduckgo-search==6.3.5<\/code>). You can directly use the original library or import the <a href=\"https:\/\/www.langchain.com\/\"><em>LangChain<\/em><\/a> wrapper (<code>pip install langchain-community==0.3.17<\/code>).\u00a0<\/p>\n<p class=\"wp-block-paragraph\">With <em>Ollama<\/em>, in order to use a Tool, the function must be described in a dictionary.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">from langchain_community.tools import DuckDuckGoSearchResults\ndef search_web(query: str) -&gt; str:\n  return DuckDuckGoSearchResults(backend=\"news\").run(query)\n\ntool_search_web = {'type':'function', 'function':{\n  'name': 'search_web',\n  'description': 'Search the web',\n  'parameters': {'type': 'object',\n                'required': ['query'],\n                'properties': {\n                    'query': {'type':'str', 'description':'the topic or subject to search on the web'},\n}}}}\n## test\nsearch_web(query=\"nvidia\")<\/code><\/pre>\n<figure class=\"wp-block-image alignwide\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXehAZbpY8-QCImneHBtFSX7Lq3Y3G2WmUOsxT4SJFm2ub-PFUQlF18ZJ27c5i830s8Of_eDb_LqZkbswZQsBXqn0oke6K1j3e12ZMBS7CRG53ngDoc1k_ko38qT51zaQd14P8HNyA?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<p class=\"wp-block-paragraph\">Internet searches could be very broad, and I want to give the Agent the option to be more precise. Let\u2019s say, I\u2019m planning to use this Agent to learn about financial updates, so I can give it a specific tool for that topic, like searching only a finance website instead of the whole web.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">def search_yf(query: str) -&gt; str:\u00a0\u00a0engine = DuckDuckGoSearchResults(backend=\"news\")\n\u00a0 return engine.run(f\"site:finance.yahoo.com {query}\")\n\ntool_search_yf = {'type':'function', 'function':{\n\u00a0 'name': 'search_yf',\n\u00a0 'description': 'Search for specific financial news',\n\u00a0 'parameters': {'type': 'object',\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 'required': ['query'],\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 'properties': {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 'query': {'type':'str', 'description':'the financial topic or subject to search'},\n}}}}\n\n## test\nsearch_yf(query=\"nvidia\")<\/code><\/pre>\n<figure class=\"wp-block-image alignwide\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXdZqW59Wu_dG6RDuNkAdhUFKoTZ_b6AVRZsJMOUDyOuzu86QCj1GFHT-wfOULv5HA2M3-ua3S_aM9YOOAidPKYSxbmR-hzzlEAd1TrGEliIeoEFwnRsKliOReJF6N2Um8ARRepdJA?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<h2 class=\"wp-block-heading\"><strong>Simple Agent (WebSearch)<\/strong><\/h2>\n<p class=\"wp-block-paragraph\">In my opinion, the most basic Agent should at least be able to choose between one or two Tools and re-elaborate the output of the action to give the user a proper and concise answer.\u00a0<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXe1P0dNkwfU17jJzcsSC9FRzwmZw_Ieq7aAdg1jvXhNsI8HMSoTzFZvFPxywt23jIBhJxl3IiOFKKecGGsXUc0HtlLt8J6DqXuaplEItC68BhXmsAsddwjii5UWJdSHjrLsxCkMPw?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<p class=\"wp-block-paragraph\">First, you need to write a prompt to describe the Agent\u2019s purpose, the more detailed the better (mine is very generic), and that will be the first message in the chat history with the LLM.\u00a0<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">prompt = '''You are an assistant with access to tools, you must decide when to use tools to answer user message.'''\u00a0\nmessages = [{\"role\":\"system\", \"content\":prompt}]<\/code><\/pre>\n<p class=\"wp-block-paragraph\">In order to keep the chat with the AI alive, I will use a loop that starts with user\u2019s input and then the Agent is invoked to respond (which can be a text from the LLM or the activation of a Tool).<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">while True:\n\u00a0 \u00a0 ## user input\n\u00a0 \u00a0 try:\n\u00a0 \u00a0 \u00a0 \u00a0 q = input('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f642.png?ssl=1\" alt=\"\ud83d\ude42\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;')\n\u00a0 \u00a0 except EOFError:\n\u00a0 \u00a0 \u00a0 \u00a0 break\n\u00a0 \u00a0 if q == \"quit\":\n\u00a0 \u00a0 \u00a0 \u00a0 break\n\u00a0 \u00a0 if q.strip() == \"\":\n\u00a0 \u00a0 \u00a0 \u00a0 continue\n\u00a0 \u00a0 messages.append( {\"role\":\"user\", \"content\":q} )\n\u00a0 \u00a0\n\u00a0 \u00a0 ## model\n\u00a0 \u00a0 agent_res = ollama.chat(\n\u00a0 \u00a0 \u00a0 \u00a0 model=llm,\n\u00a0 \u00a0 \u00a0 \u00a0 tools=[tool_search_web, tool_search_yf],\n\u00a0 \u00a0 \u00a0 \u00a0 messages=messages)<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Up to this point, the chat history could look something like this:<\/p>\n<figure class=\"wp-block-image alignwide\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXf82rIl3lfE0pjZSeqhBEZ_zA54iEubm_rJT-cOf1fDve7L9mf8utfaGL68m90Zx8-ewaKtiohhCZxQcbLDovn3bpdyUhYuLa4BruK0o4Ml8zfDM0Fs2uQBCEIYOEX4Ygw66eFxNw?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<p class=\"wp-block-paragraph\">If the model wants to use a Tool, the appropriate function needs to be run with the input parameters suggested by the LLM in its response object:<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeZzkOO1hvoJx4Ie-yKeARPXJwAuGv4xwwgZrM-tyPRRh0rq8Vkgfq0dMc80V9aB-nCzLU-hedUiYKakAaH05YsS6_IB5yUblKxDrFMLB_XlQBW_7wsxQz9dNjXXn_oZP8RDSOxxg?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<p class=\"wp-block-paragraph\">So our code needs to get that information and run the Tool function.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">## response\n\u00a0 \u00a0 dic_tools = {'search_web':search_web, 'search_yf':search_yf}\n\n\u00a0 \u00a0 if \"tool_calls\" in agent_res[\"message\"].keys():\n\u00a0 \u00a0 \u00a0 \u00a0 for tool in agent_res[\"message\"][\"tool_calls\"]:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 t_name, t_inputs = tool[\"function\"][\"name\"], tool[\"function\"][\"arguments\"]\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if f := dic_tools.get(t_name):\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ### calling tool\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 print('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f527.png?ssl=1\" alt=\"\ud83d\udd27\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;', f\"x1b[1;31m{t_name} -&gt; Inputs: {t_inputs}x1b[0m\")\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 messages.append( {\"role\":\"user\", \"content\":\"use tool '\"+t_name+\"' with inputs: \"+str(t_inputs)} )\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ### tool output\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 t_output = f(**tool[\"function\"][\"arguments\"])\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 print(t_output)\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ### final res\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 p = f'''Summarize this to answer user question, be as concise as possible: {t_output}'''\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 res = ollama.generate(model=llm, prompt=q+\". \"+p)[\"response\"]\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 else:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 print('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f92c.png?ssl=1\" alt=\"\ud83e\udd2c\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;', f\"x1b[1;31m{t_name} -&gt; NotFoundx1b[0m\")\n\u00a0\n\u00a0 \u00a0 if agent_res['message']['content'] != '':\n\u00a0 \u00a0 \u00a0 \u00a0 res = agent_res[\"message\"][\"content\"]\n\u00a0 \u00a0 \u00a0\n\u00a0 \u00a0 print(\"<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f47d.png?ssl=1\" alt=\"\ud83d\udc7d\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;\", f\"x1b[1;30m{res}x1b[0m\")\n\u00a0 \u00a0 messages.append( {\"role\":\"assistant\", \"content\":res} )<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Now, if we run the full code, we can chat with our Agent.<\/p>\n<figure class=\"wp-block-image alignwide size-large\"><img data-recalc-dims=\"1\" data-dominant-color=\"eeeeed\" data-has-transparency=\"true\" style=\"--dominant-color: #eeeeed;\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"496\" src=\"https:\/\/i0.wp.com\/towardsdatascience.com\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-20-at-8.57.45%25E2%2580%25AFAM-1024x496.png?resize=1024%2C496&#038;ssl=1\" alt=\"\" class=\"wp-image-598193 has-transparency\" srcset=\"https:\/\/towardsdatascience.com\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-20-at-8.57.45\u202fAM-1024x496.png 1024w, https:\/\/towardsdatascience.com\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-20-at-8.57.45\u202fAM-300x145.png 300w, https:\/\/towardsdatascience.com\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-20-at-8.57.45\u202fAM-768x372.png 768w, https:\/\/towardsdatascience.com\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-20-at-8.57.45\u202fAM-1536x744.png 1536w, https:\/\/towardsdatascience.com\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-20-at-8.57.45\u202fAM.png 1928w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><\/figure>\n<h2 class=\"wp-block-heading\"><strong>Advanced Agent (Coding)<\/strong><\/h2>\n<p class=\"wp-block-paragraph\">LLMs know how to code by being exposed to a large corpus of both code and natural language text, where they learn patterns, syntax, and semantics of <a href=\"https:\/\/towardsdatascience.com\/tag\/programming\/\" title=\"Programming\">Programming<\/a> languages. The model learns the relationships between different parts of the code by predicting the next token in a sequence. In short, LLMs can generate Python code but can\u2019t execute it, Agents can.<\/p>\n<p class=\"wp-block-paragraph\">I shall prepare a Tool allowing the Agent to <strong>execute code<\/strong>. In Python, you can easily create a shell to run code as a string with the native command <em>exec()<\/em>.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">import io\nimport contextlib\n\ndef code_exec(code: str) -&gt; str:\n\u00a0 \u00a0 output = io.StringIO()\n\u00a0 \u00a0 with contextlib.redirect_stdout(output):\n\u00a0 \u00a0 \u00a0 \u00a0 try:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 exec(code)\n\u00a0 \u00a0 \u00a0 \u00a0 except Exception as e:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 print(f\"Error: {e}\")\n\u00a0 \u00a0 return output.getvalue()\n\ntool_code_exec = {'type':'function', 'function':{\n\u00a0 'name': 'code_exec',\n\u00a0 'description': 'execute python code',\n\u00a0 'parameters': {'type': 'object',\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 'required': ['code'],\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 'properties': {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 'code': {'type':'str', 'description':'code to execute'},\n}}}}\n\n## test\ncode_exec(\"a=1+1; print(a)\")<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Just like before, I will write a prompt, but this time, at the beginning of the chat-loop, I will ask the user to provide a file path.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">prompt = '''You are an expert data scientist, and you have tools to execute python code.\nFirst of all, execute the following code exactly as it is: 'df=pd.read_csv(path); print(df.head())'\nIf you create a plot, ALWAYS add 'plt.show()' at the end.\n'''\nmessages = [{\"role\":\"system\", \"content\":prompt}]\nstart = True\n\nwhile True:\n\u00a0 \u00a0 ## user input\n\u00a0 \u00a0 try:\n\u00a0 \u00a0 \u00a0 \u00a0 if start is True:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 path = input('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f4c1.png?ssl=1\" alt=\"\ud83d\udcc1\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> Provide a CSV path &gt;')\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 q = \"path = \"+path\n\u00a0 \u00a0 \u00a0 \u00a0 else:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 q = input('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f642.png?ssl=1\" alt=\"\ud83d\ude42\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;')\n\u00a0 \u00a0 except EOFError:\n\u00a0 \u00a0 \u00a0 \u00a0 break\n\u00a0 \u00a0 if q == \"quit\":\n\u00a0 \u00a0 \u00a0 \u00a0 break\n\u00a0 \u00a0 if q.strip() == \"\":\n\u00a0 \u00a0 \u00a0 \u00a0 continue\n\u00a0 \u00a0\n\u00a0 \u00a0 messages.append( {\"role\":\"user\", \"content\":q} )<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Since coding tasks can be a little trickier for LLMs, I am going to add also <strong>memory reinforcement<\/strong>. By default, during one session, there isn\u2019t a true long-term memory. LLMs have access to the chat history, so they can remember information temporarily, and track the context and instructions you\u2019ve given earlier in the conversation. However, memory doesn\u2019t always work as expected, especially if the LLM is small. Therefore, a good practice is to reinforce the model\u2019s memory by adding periodic reminders in the chat history.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-python\">prompt = '''You are an expert data scientist, and you have tools to execute python code.\nFirst of all, execute the following code exactly as it is: 'df=pd.read_csv(path); print(df.head())'\nIf you create a plot, ALWAYS add 'plt.show()' at the end.\n'''\nmessages = [{\"role\":\"system\", \"content\":prompt}]\nmemory = '''Use the dataframe 'df'.'''\nstart = True\n\nwhile True:\n\u00a0 \u00a0 ## user input\n\u00a0 \u00a0 try:\n\u00a0 \u00a0 \u00a0 \u00a0 if start is True:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 path = input('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f4c1.png?ssl=1\" alt=\"\ud83d\udcc1\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> Provide a CSV path &gt;')\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 q = \"path = \"+path\n\u00a0 \u00a0 \u00a0 \u00a0 else:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 q = input('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f642.png?ssl=1\" alt=\"\ud83d\ude42\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;')\n\u00a0 \u00a0 except EOFError:\n\u00a0 \u00a0 \u00a0 \u00a0 break\n\u00a0 \u00a0 if q == \"quit\":\n\u00a0 \u00a0 \u00a0 \u00a0 break\n\u00a0 \u00a0 if q.strip() == \"\":\n\u00a0 \u00a0 \u00a0 \u00a0 continue\n\u00a0 \u00a0\n\u00a0 \u00a0 ## memory\n\u00a0 \u00a0 if start is False:\n\u00a0 \u00a0 \u00a0 \u00a0 q = memory+\"n\"+q\n\u00a0 \u00a0 messages.append( {\"role\":\"user\", \"content\":q} )<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Please note that the default memory length in Ollama is 2048 characters. If your machine can handle it, you can increase it by changing the number when the LLM is invoked:<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">\u00a0 \u00a0 ## model\n\u00a0 \u00a0 agent_res = ollama.chat(\n\u00a0 \u00a0 \u00a0 \u00a0 model=llm,\n\u00a0 \u00a0 \u00a0 \u00a0 tools=[tool_code_exec],\n\u00a0 \u00a0 \u00a0 \u00a0 options={\"num_ctx\":2048},\n\u00a0 \u00a0 \u00a0 \u00a0 messages=messages)<\/code><\/pre>\n<p class=\"wp-block-paragraph\">In this usecase, the output of the Agent is mostly code and data, so I don\u2019t want the LLM to re-elaborate the responses.<\/p>\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">\u00a0 \u00a0 ## response\n\u00a0 \u00a0 dic_tools = {'code_exec':code_exec}\n\u00a0 \u00a0\n\u00a0 \u00a0 if \"tool_calls\" in agent_res[\"message\"].keys():\n\u00a0 \u00a0 \u00a0 \u00a0 for tool in agent_res[\"message\"][\"tool_calls\"]:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 t_name, t_inputs = tool[\"function\"][\"name\"], tool[\"function\"][\"arguments\"]\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if f := dic_tools.get(t_name):\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ### calling tool\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 print('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f527.png?ssl=1\" alt=\"\ud83d\udd27\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;', f\"x1b[1;31m{t_name} -&gt; Inputs: {t_inputs}x1b[0m\")\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 messages.append( {\"role\":\"user\", \"content\":\"use tool '\"+t_name+\"' with inputs: \"+str(t_inputs)} )\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ### tool output\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 t_output = f(**tool[\"function\"][\"arguments\"])\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ### final res\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 res = t_output\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 else:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 print('<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f92c.png?ssl=1\" alt=\"\ud83e\udd2c\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;', f\"x1b[1;31m{t_name} -&gt; NotFoundx1b[0m\")\n\u00a0\n\u00a0 \u00a0 if agent_res['message']['content'] != '':\n\u00a0 \u00a0 \u00a0 \u00a0 res = agent_res[\"message\"][\"content\"]\n\u00a0 \u00a0 \u00a0\n\u00a0 \u00a0 print(\"<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f47d.png?ssl=1\" alt=\"\ud83d\udc7d\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"> &gt;\", f\"x1b[1;30m{res}x1b[0m\")\n\u00a0 \u00a0 messages.append( {\"role\":\"assistant\", \"content\":res} )\n\u00a0 \u00a0 start = False<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Now, if we run the full code, we can chat with our Agent.<\/p>\n<figure class=\"wp-block-image alignwide\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfYCvpQmAdh1O7ndDTxwIRJzE4zIG7wOugEjAhNF8ueVmHjHpHEWaTYY8hrIvF5w-1klpYWRYxyBQu9famAIJjc_Dlb0J5Hm8h5Q5B2I4bi8B4yk3zzG1ZRtd8uZeB58_UTdDQ2?key=iR_ydAF7p6lG2ks6jCALweHO\" alt=\"\"><\/figure>\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n<p class=\"wp-block-paragraph\">This article has covered the foundational steps of creating Agents from scratch using only <em>Ollama<\/em>. With these building blocks in place, you are already equipped to start developing your own Agents for different use cases.\u00a0<\/p>\n<p class=\"wp-block-paragraph\"><strong>Stay tuned for Part 2<\/strong>, where we will dive deeper into more advanced examples.<\/p>\n<p class=\"wp-block-paragraph\">Full code for this article: <a href=\"https:\/\/github.com\/mdipietro09\/GenerativeAI\/blob\/main\/Agents_ZeroToHero\/notebook.ipynb\"><strong>GitHub<\/strong><\/a><\/p>\n<p class=\"wp-block-paragraph\">I hope you enjoyed it! Feel free to contact me for questions and feedback or just to share your interesting projects.<\/p>\n<p class=\"wp-block-paragraph\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f449.png?ssl=1\" alt=\"\ud83d\udc49\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\">\u00a0<a href=\"https:\/\/maurodp.carrd.co\/\"><strong>Let\u2019s Connect<\/strong><\/a>\u00a0<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/1f448.png?ssl=1\" alt=\"\ud83d\udc48\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\"><\/p>\n<p>The post <a href=\"https:\/\/towardsdatascience.com\/ai-agents-from-zero-to-hero-part-1\/\">AI Agents from Zero to Hero \u2013 Part 1<\/a> appeared first on <a href=\"https:\/\/towardsdatascience.com\/\">Towards Data Science<\/a>.<\/p>\n<\/div>\n<p> \t<BR><br \/>\n <BR><\/BR><br \/>\n    Mauro Di Pietro<br \/>\n \t<BR><br \/>\n<BR><\/BR><br \/>\n<a href=\"https:\/\/towardsdatascience.com\/ai-agents-from-zero-to-hero-part-1\/\">Go to original source<\/a><br \/>\n \t<BR><br \/>\n <BR><\/BR><\/p>\n","protected":false},"excerpt":{"rendered":"<p>AI Agents from Zero to Hero \u2013 Part 1 Intro AI Agents are autonomous programs that perform tasks, make decisions, and communicate with others. Normally, they use a set of tools to help complete tasks. In GenAI applications, these Agents process sequential reasoning and can use external tools (like web searches or database queries) when [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[678,799,62,69,87,722,160],"tags":[1140,98,291],"class_list":["post-1978","post","type-post","status-publish","format-standard","hentry","category-agentic-ai","category-ai-agent","category-aimldsaimlds","category-artificial-intelligence","category-llm","category-ollama","category-programming","tag-agents","tag-ai","tag-use"],"_links":{"self":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts\/1978"}],"collection":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/comments?post=1978"}],"version-history":[{"count":0,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts\/1978\/revisions"}],"wp:attachment":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/media?parent=1978"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/categories?post=1978"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/tags?post=1978"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}