From ebd40d6568a9450c0156a8021ee773c37162b994 Mon Sep 17 00:00:00 2001 From: MichaelisTrofficus Date: Thu, 24 Oct 2024 15:42:10 +0200 Subject: [PATCH 1/6] add more sections to readme --- README.md | 272 +++++++++++++++++++++++++++++ img/dag.svg | 42 +++++ notebooks/reflection_pattern.ipynb | 2 +- 3 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 img/dag.svg diff --git a/README.md b/README.md index 6e36f73..929136b 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,20 @@ > No LangChain, no LangGraph, no LlamaIndex, no CrewAI. Pure and simple API calls to Groq. +## Table of Contents + +- [1. Introduction](#introduction) + - [1.1 Reflection Pattern](#reflection-pattern-) + - [1.2 Tool Pattern](#tool-pattern--) + - [1.3 Planning Pattern](#planning-pattern-) + - [1.4 Multiagent Pattern](#multiagent-pattern-) + +- [2. The 4 Agentic Patterns](#the-4-agentic-patterns) + +- [3. Install & Usage](#install--usage) +- [4. Recommended Workflow](#recommended-workflow) +- [5. Star History](#star-history) + ## Introduction @@ -120,6 +134,264 @@ Take a look at the YouTube video! 👇 [![Watch the video](https://img.youtube.com/vi/os22Q7nEXPA/0.jpg)](https://www.youtube.com/watch?v=os22Q7nEXPA) --- +## Install & Usage + +If you take a look at any of the notebooks in the [notebooks/](notebooks) folder you'll see some helper methods and classes being imported from this library: `agentic-patterns`. + +This is the library implemented in the [src/](src) folder, and contains a full implementation of the 4 patterns and related helper methods. + +To install this library, you have two options: + + 1. Use [Poetry](https://python-poetry.org/): + +``` +poetry install +``` + +2. Use pip (I've created a [Python package in Pypi](https://pypi.org/project/agentic-patterns/)) + +```sh +pip install -U agentic-patterns +``` + +Once you have the library installed, you can start playing with the 4 patterns implementation (I'll encourage you to take a look at the code, to fully understand what is happening under the hood). + +Let's see an example of how to put the 4 patterns into practise. + +### Example of Reflection Pattern + +Here is an example of how to use a Reflection Agent. + +```python +from agentic_patterns import ReflectionAgent + +agent = ReflectionAgent() + +generation_system_prompt = "You are a Python programmer tasked with generating high quality Python code" + +reflection_system_prompt = "You are Andrej Karpathy, an experienced computer scientist" + +user_msg = "Generate a Python implementation of the Merge Sort algorithm" + + +final_response = agent.run( + user_msg=user_msg, + generation_system_prompt=generation_system_prompt, + reflection_system_prompt=reflection_system_prompt, + n_steps=10, + verbose=1, +) + +print(final_response) +``` + +### Example of Tool Pattern + +An example of how to create a custom tool and bind it to a Tool Agent. + +First, let's create the tool. In this case, I'll be creating a tool for interacting with Hacker News. To define a tool, we just need to decorate the Python function with the `@tool`decorator. + +```python +import json +import requests +from agentic_patterns.tool_pattern.tool import tool +from agentic_patterns.tool_pattern.tool_agent import ToolAgent + +@tool +def fetch_top_hacker_news_stories(top_n: int): + """ + Fetch the top stories from Hacker News. + + This function retrieves the top `top_n` stories from Hacker News using the Hacker News API. + Each story contains the title, URL, score, author, and time of submission. The data is fetched + from the official Firebase Hacker News API, which returns story details in JSON format. + + Args: + top_n (int): The number of top stories to retrieve. + """ + top_stories_url = 'https://hacker-news.firebaseio.com/v0/topstories.json' + + try: + response = requests.get(top_stories_url) + response.raise_for_status() # Check for HTTP errors + + # Get the top story IDs + top_story_ids = response.json()[:top_n] + + top_stories = [] + + # For each story ID, fetch the story details + for story_id in top_story_ids: + story_url = f'https://hacker-news.firebaseio.com/v0/item/{story_id}.json' + story_response = requests.get(story_url) + story_response.raise_for_status() # Check for HTTP errors + story_data = story_response.json() + + # Append the story title and URL (or other relevant info) to the list + top_stories.append({ + 'title': story_data.get('title', 'No title'), + 'url': story_data.get('url', 'No URL available'), + }) + + return json.dumps(top_stories) + + except requests.exceptions.RequestException as e: + print(f"An error occurred: {e}") + return [] +``` + +Next, let's define the Agent. + +```python +tool_agent = ToolAgent(tools=[fetch_top_hacker_news_stories]) + +output = tool_agent.run(user_msg="Tell me the top 5 Hacker News stories right now") + +print(output) +``` + +### Example of Planning Pattern + +As a paradigmatic example of the Planning Pattern, `agentic-patterns` offers an implementation of a ReAct Agent. + +The `ReactAgent` is an evolution of the `ToolAgent`, extending its planning and reasoning capabilities. + +As we did before, we'll begin by defining the tools. In this case, I'll create three. + +```python +@tool +def sum_two_elements(a: int, b: int) -> int: + """ + Computes the sum of two integers. + + Args: + a (int): The first integer to be summed. + b (int): The second integer to be summed. + + Returns: + int: The sum of `a` and `b`. + """ + return a + b + + +@tool +def multiply_two_elements(a: int, b: int) -> int: + """ + Multiplies two integers. + + Args: + a (int): The first integer to multiply. + b (int): The second integer to multiply. + + Returns: + int: The product of `a` and `b`. + """ + return a * b + +@tool +def compute_log(x: int) -> float | str: + """ + Computes the logarithm of an integer `x` with an optional base. + + Args: + x (int): The integer value for which the logarithm is computed. Must be greater than 0. + + Returns: + float: The logarithm of `x` to the specified `base`. + """ + if x <= 0: + return "Logarithm is undefined for values less than or equal to 0." + + return math.log(x) +``` + +Now, let's create the agent. + +```python +from agentic_patterns.planning_pattern.react_agent import ReactAgent + +agent = ReactAgent(tools=[sum_two_elements, multiply_two_elements, compute_log]) + +agent.run(user_msg="I want to calculate the sum of 1234 and 5678 and multiply the result by 5. Then, I want to take the logarithm of this result") +``` + +### Example of MultiAgent Pattern + +For the Multiagent Pattern, I decided to use two [CrewAI](https://www.crewai.com/)'s abstractions: the Agent and the Crew. + +Additionally, I've also borrow some ideas from Airflow, defining the dependency between agents using the `>>` operator. + +Let's see an example: + +```python +from agentic_patterns.multiagent_pattern.crew import Crew + + +with Crew() as crew: + agent_1 = Agent( + name="Poet Agent", + backstory="You are a well-known poet, who enjoys creating high quality poetry.", + task_description="Write a poem about the meaning of life", + task_expected_output="Just output the poem, without any title or introductory sentences", + ) + + agent_2 = Agent( + name="Poem Translator Agent", + backstory="You are an expert translator especially skilled in Spanish", + task_description="Translate a poem into Spanish", + task_expected_output="Just output the translated poem and nothing else" + ) + + agent_3 = Agent( + name="Writer Agent", + backstory="You are an expert transcriber, that loves writing poems into txt files", + task_description="You'll receive a Spanish poem in your context. You need to write the poem into './poem.txt' file", + task_expected_output="A txt file containing the greek poem received from the context", + tools=write_str_to_txt, + ) + + agent_1 >> agent_2 >> agent_3 +``` + +We can also plot the Crew, to see the DAG structure, like this: + +```python +crew.plot() +``` + +For the previous Crew, you should get something like this: + +![alt text](img/dag.svg) + +To run the Crew, simply run: + +```python +crew.run() +``` + +## Recommended Workflow + +This is **an educational project** and not an agentic framework. + +The reason I've decided to implement the 4 Agentic Patterns from scratch was to deeply understand their basics and also to teach them to anyone interested. + +Given this, this is my recommended learning workflow: + +1. Start with the YouTube video, ideally following my explanations with your own Jupyter Notebook. + +2. Play with the code in the Jupyter Notebook: make changes, modify the prompts, create new examples etc. Get comfortable with the pattern fundamentals and basic concepts. + +3. (Optional) Read through the library implementation of each pattern. This will require more effort and more Python knowledge, but if you take the time, I can assure you you'll benefit a lot from it. + +```mermaid +flowchart TD; + Video --> Notebook; + Notebook --> Code + classDef centered text-align:center; +``` + + + ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=neural-maze/agentic_patterns&type=Date)](https://star-history.com/#neural-maze/agentic_patterns&Date) \ No newline at end of file diff --git a/img/dag.svg b/img/dag.svg new file mode 100644 index 0000000..62ad30d --- /dev/null +++ b/img/dag.svg @@ -0,0 +1,42 @@ + + + + + + + + + +Poet Agent + +Poet Agent + + + +Poem Translator Agent + +Poem Translator Agent + + + +Poet Agent->Poem Translator Agent + + + + + +Writer Agent + +Writer Agent + + + +Poem Translator Agent->Writer Agent + + + + + diff --git a/notebooks/reflection_pattern.ipynb b/notebooks/reflection_pattern.ipynb index 91ccf70..31b6241 100644 --- a/notebooks/reflection_pattern.ipynb +++ b/notebooks/reflection_pattern.ipynb @@ -1131,7 +1131,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": ".venv", "language": "python", "name": "python3" }, From 2c445cd28c6e86b71d3d34406eab7549dddf6c15 Mon Sep 17 00:00:00 2001 From: MichaelisTrofficus Date: Thu, 24 Oct 2024 16:02:42 +0200 Subject: [PATCH 2/6] center elements --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 929136b..69f4e5e 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,11 @@ Want to see how this pattern is implemented? 💻 - Check the [`Tool`](src/agentic_patterns/tool_pattern/tool.py) for understanding how Tools work under the hood. Take a look at the YouTube video! 👇 - -[![Watch the video](https://img.youtube.com/vi/ApoDzZP8_ck/0.jpg)](https://www.youtube.com/watch?v=ApoDzZP8_ck) - +
+ + Watch the video + +
--- ### Planning Pattern 🧠 @@ -361,7 +363,9 @@ crew.plot() For the previous Crew, you should get something like this: -![alt text](img/dag.svg) +
+ alt text +
To run the Crew, simply run: From 880fab4d70b8cb78de8b37d3dc9cfa6cf8605a3a Mon Sep 17 00:00:00 2001 From: MichaelisTrofficus Date: Thu, 24 Oct 2024 16:21:44 +0200 Subject: [PATCH 3/6] improve readme.md --- README.md | 64 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 69f4e5e..e8c15a7 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,14 @@ - [2. The 4 Agentic Patterns](#the-4-agentic-patterns) -- [3. Install & Usage](#install--usage) -- [4. Recommended Workflow](#recommended-workflow) -- [5. Star History](#star-history) +- [3. Installation](#installation) +- [4. Usage](#usage) + - [4.1 Using a Reflection Agent - Reflection Pattern](#using-a-reflection-agent---reflection-pattern) + - [4.2 Creating and Using Tools - Tool Use Pattern](#creating-and-using-tools---tool-use-pattern) + - [4.3 Reasoning with a ReAct Agent - Planning Pattern](#reasoning-with-a-react-agent---planning-pattern) + - [4.4 Defining and running a Crew of Agents - MultiAgent Pattern](#defining-and-running-a-crew-of-agents---multiagent-pattern) +- [5. Recommended Workflow](#recommended-workflow) +- [6. Star History](#star-history) ## Introduction @@ -54,9 +59,11 @@ Want to see how this pattern is implemented? 💻 Take a look at the YouTube video! 👇 -[![Watch the video](https://img.youtube.com/vi/0sAVI8bQdRc/0.jpg)](https://www.youtube.com/watch?v=0sAVI8bQdRc) - - +
+ + Watch the video + +
--- @@ -86,6 +93,7 @@ Take a look at the YouTube video! 👇 Watch the video + --- ### Planning Pattern 🧠 @@ -108,8 +116,11 @@ Want to see how this pattern is implemented? 💻 Take a look at the YouTube video! 👇 -[![Watch the video](https://img.youtube.com/vi/4xkC069wrw8/0.jpg)](https://www.youtube.com/watch?v=4xkC069wrw8) - +
+ + Watch the video + +
--- @@ -133,34 +144,45 @@ the `Crew` Take a look at the YouTube video! 👇 -[![Watch the video](https://img.youtube.com/vi/os22Q7nEXPA/0.jpg)](https://www.youtube.com/watch?v=os22Q7nEXPA) +
+ + Watch the video + +
+ --- -## Install & Usage +## Installation If you take a look at any of the notebooks in the [notebooks/](notebooks) folder you'll see some helper methods and classes being imported from this library: `agentic-patterns`. This is the library implemented in the [src/](src) folder, and contains a full implementation of the 4 patterns and related helper methods. -To install this library, you have two options: +To install this library, you have two options. - 1. Use [Poetry](https://python-poetry.org/): + ### Option 1: Use [Poetry](https://python-poetry.org/): ``` poetry install ``` -2. Use pip (I've created a [Python package in Pypi](https://pypi.org/project/agentic-patterns/)) +### Option 2: Install the PyPi library ```sh pip install -U agentic-patterns ``` +--- + +## Usage + Once you have the library installed, you can start playing with the 4 patterns implementation (I'll encourage you to take a look at the code, to fully understand what is happening under the hood). Let's see an example of how to put the 4 patterns into practise. -### Example of Reflection Pattern +--- + +### Using a Reflection Agent - Reflection Pattern Here is an example of how to use a Reflection Agent. @@ -187,7 +209,7 @@ final_response = agent.run( print(final_response) ``` -### Example of Tool Pattern +### Creating and Using Tools - Tool Use Pattern An example of how to create a custom tool and bind it to a Tool Agent. @@ -252,7 +274,7 @@ output = tool_agent.run(user_msg="Tell me the top 5 Hacker News stories right no print(output) ``` -### Example of Planning Pattern +### Reasoning with a ReAct Agent - Planning Pattern As a paradigmatic example of the Planning Pattern, `agentic-patterns` offers an implementation of a ReAct Agent. @@ -317,7 +339,7 @@ agent = ReactAgent(tools=[sum_two_elements, multiply_two_elements, compute_log]) agent.run(user_msg="I want to calculate the sum of 1234 and 5678 and multiply the result by 5. Then, I want to take the logarithm of this result") ``` -### Example of MultiAgent Pattern +### Defining and running a Crew of Agents - MultiAgent Pattern For the Multiagent Pattern, I decided to use two [CrewAI](https://www.crewai.com/)'s abstractions: the Agent and the Crew. @@ -381,11 +403,11 @@ The reason I've decided to implement the 4 Agentic Patterns from scratch was to Given this, this is my recommended learning workflow: -1. Start with the YouTube video, ideally following my explanations with your own Jupyter Notebook. +1️⃣ Start with the YouTube video, ideally following my explanations with your own Jupyter Notebook. -2. Play with the code in the Jupyter Notebook: make changes, modify the prompts, create new examples etc. Get comfortable with the pattern fundamentals and basic concepts. +2️⃣ Play with the code in the Jupyter Notebook: make changes, modify the prompts, create new examples etc. Get comfortable with the pattern fundamentals and basic concepts. -3. (Optional) Read through the library implementation of each pattern. This will require more effort and more Python knowledge, but if you take the time, I can assure you you'll benefit a lot from it. +3️⃣ (Optional) Read through the library implementation of each pattern. This will require more effort and more Python knowledge, but if you take the time, I can assure you you'll benefit a lot from it. ```mermaid flowchart TD; @@ -394,8 +416,6 @@ flowchart TD; classDef centered text-align:center; ``` - - ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=neural-maze/agentic_patterns&type=Date)](https://star-history.com/#neural-maze/agentic_patterns&Date) \ No newline at end of file From bcf8db6b0f4c5a54834196e03dfaf23a8508ef9d Mon Sep 17 00:00:00 2001 From: MichaelisTrofficus Date: Thu, 24 Oct 2024 16:40:42 +0200 Subject: [PATCH 4/6] clear status of notebooks --- notebooks/multiagent_pattern.ipynb | 398 +--------------- notebooks/planning_pattern.ipynb | 227 ++------- notebooks/reflection_pattern.ipynb | 742 +---------------------------- notebooks/tool_pattern.ipynb | 198 ++------ 4 files changed, 122 insertions(+), 1443 deletions(-) diff --git a/notebooks/multiagent_pattern.ipynb b/notebooks/multiagent_pattern.ipynb index 0ed8c70..923ab0d 100644 --- a/notebooks/multiagent_pattern.ipynb +++ b/notebooks/multiagent_pattern.ipynb @@ -53,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "69780ba5-c321-4d71-b0aa-35b1d6c55ff3", "metadata": {}, "outputs": [], @@ -71,7 +71,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "3aa589d5-7825-4fe0-a269-f35474bf6da5", "metadata": {}, "outputs": [], @@ -86,41 +86,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "fd71e1e3-893f-40e1-b6c5-f15e42beb851", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "In realms of existence, we wander and roam \n", - "searching for answers to an eternal home \n", - "a place where hearts can find their peaceful nest \n", - "where love and laughter are the ultimate quest \n", - "\n", - "In moments of joy, we grasp and we hold \n", - "the beauty of life, like a story unfold \n", - "in sorrow's darkness, we seek to find \n", - "a glimmer of hope, a light left behind \n", - "\n", - "Perhaps the meaning of life is not one thing \n", - "but a tapestry woven with every heartbeat's ring \n", - "a kaleidoscope of moments, shining bright \n", - "a dance between darkness and the light \n", - "\n", - "Maybe it's found in the love we give and share \n", - "in the connection of hearts, beyond compare \n", - "or perhaps in the solo journey of the soul \n", - "where the whispers of the heart make us whole \n", - "\n", - "In the grand symphony of existence and time \n", - "each note unique, yet together intertwined \n", - "the meaning of life, a mystery divine \n", - "unfolding like a rose, in every moment's design\n" - ] - } - ], + "outputs": [], "source": [ "print(agent_example.run())" ] @@ -135,7 +104,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "b7fae777-3bf6-4be5-8ab8-de79f545d25a", "metadata": {}, "outputs": [], @@ -145,7 +114,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "4016dc0d-cc7f-4e7a-b971-2ecfd31b79cf", "metadata": {}, "outputs": [], @@ -171,7 +140,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "7ed9d5c5-6a1a-4510-85a1-5c03c2d2fa37", "metadata": {}, "outputs": [], @@ -187,40 +156,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "a6214dc3-e24f-430c-99f0-6a8fe484d8ba", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[35m\n", - "Thought: I need to take the given string and write it to a .txt file with a specified name\n", - "\u001b[32m\n", - "Using Tool: write_str_to_txt\n", - "\u001b[32m\n", - "Tool call dict: \n", - "{'name': 'write_str_to_txt', 'arguments': {'string_data': 'This is a Tool Agent', 'txt_filename': './tool_agent_example.txt'}, 'id': 0}\n", - "Data successfully written to ./tool_agent_example.txt\n", - "\u001b[32m\n", - "Tool result: \n", - "None\n", - "\u001b[34m\n", - "Observations: {0: None}\n" - ] - }, - { - "data": { - "text/plain": [ - "'A .txt file containing the given string'" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "agent_tool_example.run()" ] @@ -243,7 +182,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "bf142278-b556-42cb-9a5e-2761af96f5c0", "metadata": {}, "outputs": [], @@ -273,21 +212,10 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "f52347ac-99b3-4695-a6a4-cf31f7784826", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Poem Translator Agent" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "agent_1 >> agent_2" ] @@ -302,21 +230,10 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "560148d0-ae20-45ba-b22f-938eda0be64d", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Agent 1 dependencies: []\n", - "Agent 1 dependents: [Poem Translator Agent]\n", - "Agent 2 dependencies: [Poet Agent]\n", - "Agent 2 dependents: []\n" - ] - } - ], + "outputs": [], "source": [ "print(\"Agent 1 dependencies: \", agent_1.dependencies)\n", "print(\"Agent 1 dependents: \", agent_1.dependents)\n", @@ -334,89 +251,20 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "26f58fda-3673-4067-ad0b-a4055a476a32", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "In whispered winds that gently sway,\n", - "A mystery unfolds each passing day,\n", - "A question mark that echoes through our years,\n", - "What meaning lies behind our laughter, joy and tears?\n", - "\n", - "Is it the bloom of love that takes our breath?\n", - "Or summer sunshine that brings warmth to our death?\n", - "Perhaps it's the quiet peaceful nights that come,\n", - "And the stillness that illuminates, like the morning's gentle hum.\n", - "\n", - "Is life a fleeting dream that we all chase?\n", - "A pursuit of dreams, with moments we can't replace?\n", - "Or is it the collective tapestry we weave?\n", - "Where each thread's meaning intersects, the hearts we give and retrieve.\n", - "\n", - "In nature's depths, in art and love we find our truth,\n", - "In connection with each soul, the beat of our youth,\n", - "And as our seasons unfold, we begin to realize,\n", - "Life's meaning lies not in its length, but in the moment's gentle sigh.\n", - "\n", - "Yet meaning's never-ending quest that beats within our heart,\n", - "Leads us to weave a patchwork of love, our lives' unwinding art,\n", - "In searching for the puzzle's end, we find its pieces key,\n", - "In living, learning, growing and loving, a life well-lived we see.\n", - "\n", - "Perhaps life's meaning lies not in a single thread,\n", - "But a rich tapestry that countless moments of love and time now wove and spread.\n" - ] - } - ], + "outputs": [], "source": [ "print(agent_1.run())" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "cd3dccc9-c201-4a70-bebf-1b9b83b7f59d", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Poem Translator Agent received context: \n", - "In whispered winds that gently sway,\n", - "A mystery unfolds each passing day,\n", - "A question mark that echoes through our years,\n", - "What meaning lies behind our laughter, joy and tears?\n", - "\n", - "Is it the bloom of love that takes our breath?\n", - "Or summer sunshine that brings warmth to our death?\n", - "Perhaps it's the quiet peaceful nights that come,\n", - "And the stillness that illuminates, like the morning's gentle hum.\n", - "\n", - "Is life a fleeting dream that we all chase?\n", - "A pursuit of dreams, with moments we can't replace?\n", - "Or is it the collective tapestry we weave?\n", - "Where each thread's meaning intersects, the hearts we give and retrieve.\n", - "\n", - "In nature's depths, in art and love we find our truth,\n", - "In connection with each soul, the beat of our youth,\n", - "And as our seasons unfold, we begin to realize,\n", - "Life's meaning lies not in its length, but in the moment's gentle sigh.\n", - "\n", - "Yet meaning's never-ending quest that beats within our heart,\n", - "Leads us to weave a patchwork of love, our lives' unwinding art,\n", - "In searching for the puzzle's end, we find its pieces key,\n", - "In living, learning, growing and loving, a life well-lived we see.\n", - "\n", - "Perhaps life's meaning lies not in a single thread,\n", - "But a rich tapestry that countless moments of love and time now wove and spread.\n" - ] - } - ], + "outputs": [], "source": [ "print(agent_2.context)" ] @@ -431,45 +279,10 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "a686cefc-db4f-4eb4-9e93-11bdbdd30d6d", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ἀ.eduκτὰ συγνώμη τὰ σόγονα που ψιθύρουν καὶ που εἶναι εἰρήνεια,\n", - "\n", - "Μυστήριο ἀνοίγει διαρκῶς καλούμενοι,\n", - "Ἐρώτημα ἕνα που ἐλέγξει τὰ ἡλικώματα μας,\n", - "Τί σημαίνουν πίσω ἀπὸ τὰ γέλια μας, χαρά καὶ δάκρυα;\n", - "\n", - "Ἢ εἶναι ἡ ἄνθηση τῆς ἀγάπης που παίρνει τὸ ἄφθονο màς;\n", - "Ἢ ἡ θέρος ἡλιοφάνεια που βραβεύει θερμότητα στο θάνατο μας;\n", - "Ἢ ἴσως εἶναι τὰ ἡσύχια παλαίωναν που ἔρχεται,\n", - "Και ἡ ἠρεμία που φωτίζει, ὅπως τὸ πρωΐνὸν ὕφος;\n", - "\n", - "Ἢ εἶναι ἡ ζωὴ εἴδωλο που ὅλοι κυνηγοῦμε;\n", - "Ἐξόφλησις ὀνείρων, με τὰ κρυστάλλινα κῶλα που δέν τον καθαρισμό;\n", - "Ἢ εἶναι ἡ συλλεκτική tapisserie που ὑφαίνουμε;\n", - "Ὁπου ἡ κάθε νήμα εἶναι ἡ σημασία που διασταυρώνεται, τznamὴ καρδιές που δίναμε καὶ παίρνουμε.\n", - "\n", - "Στὴ φύση βρύν, στὴ τέχνη καὶ τῆ ἀγάπη που εὑρίσκουμε τὴν ἀλήθεια μας,\n", - "Στὴ σύνδεση με τὴν ψυχή, ἡ κρούση τῶν νιάτων;\n", - "Και ὅσο ξετυλίγονται οἱ καιροί μας, ἀρχίζουμε νὰ συνοραῖστε,\n", - "Ἡ σημασία τῆς ζωῆς βρὶσκεται ὄχι στο μῆκος ἀλλά τὴ δYG ὑπὲρ τῆσ momentos εἰδικώ.\n", - "\n", - "Ἀλλὰ ἡ ἀναζήτηση τῆς σημασίας ποὺ παίρνει ἡ κρύπτη στὴ καρδιά μας,\n", - "Μᾶς ὁδηγεῖ νὰ ὑφάνουμε καλαμίδα ἀγάπης, τὴν τέχνη τῆς ζωῆς μας.\n", - "Ἐν τῶ ἀναζητῶν τὸ τέλος τοῦ puzzle, εὑρίσκουμε το κλειδί,\n", - "Στὴ ζωή, στὴ μάθηση, τὴν ἀνάπτυξη καὶ τὴν ἀγάπη, μιᾶς ζωὴς καλά ἔζη.\n", - "\n", - "Ἰσώ εἶναι ἡ σημασία τῆς ζωῆς που βρὶσκεται ὄχι σὲ ἕνα ἴναιο,\n", - "Ἀλλὰ σὲ πλούσια tapisserie που ἀπείρως απόστολος ἀγάπης καὶ χρόνου ἤδη ἥνωσε καὶ ἄνειψε.\n" - ] - } - ], + "outputs": [], "source": [ "print(agent_2.run())" ] @@ -484,7 +297,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "66c83cc4-87cf-4afc-855b-e5263ad95a71", "metadata": {}, "outputs": [], @@ -494,7 +307,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "id": "e58d1cbd-3dbb-4a36-8fc8-9b4242a7b1d3", "metadata": {}, "outputs": [], @@ -527,179 +340,20 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "id": "9027cbdc-2bb0-419b-87a0-0352f59d3079", "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "Poet Agent\n", - "\n", - "Poet Agent\n", - "\n", - "\n", - "\n", - "Poem Translator Agent\n", - "\n", - "Poem Translator Agent\n", - "\n", - "\n", - "\n", - "Poet Agent->Poem Translator Agent\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "Writer Agent\n", - "\n", - "Writer Agent\n", - "\n", - "\n", - "\n", - "Poem Translator Agent->Writer Agent\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "crew.plot()" ] }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "id": "b39f70a0-2c91-40c4-ab56-8318cef7ef97", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1m\u001b[36m\n", - "==================================================\n", - "\u001b[35mRUNNING AGENT: Poet Agent\n", - "\u001b[1m\u001b[36m==================================================\n", - "\n", - "\u001b[31mIn the grand tapestry of time and space,\n", - "A thread of existence weaves its place,\n", - "A fleeting moment, a spark of might,\n", - "A life that burns, and flickers in the night.\n", - "\n", - "We dance upon the earth, with feet of clay,\n", - " Searching for answers, night and day,\n", - "We toil and struggle, we laugh and play,\n", - "Yet in the end, what does it all convey?\n", - "\n", - "Some say it's purpose, some say it's fate,\n", - "Some claim to know, while others hesitate,\n", - "But as we journey through life's twisted gate,\n", - "We begin to see, our own path create.\n", - "\n", - "Perhaps the meaning lies, not in the end,\n", - "But in the journey, the love, the friend,\n", - "The sun-kissed days, the starry nights,\n", - "The memories we hold, the laughter, the fights.\n", - "\n", - "Or maybe it's a mystery we'll never know,\n", - "A truth that's hidden, in the cosmos' glow,\n", - "A secret that only the universe can share,\n", - "A riddle that's solved, only in the silence we spare.\n", - "\n", - "But this we do know, in this life we lead,\n", - "We have the power, to plant the seed,\n", - "To nurture growth, to tend the earth,\n", - "To make our mark, to give our mirth.\n", - "\n", - "And when our time is done, and we're gone,\n", - "Our legacy remains, like the morning sun,\n", - "A light that shines, a love that's true,\n", - "A memory that lives, in the hearts of me and you.\n", - "\u001b[1m\u001b[36m\n", - "==================================================\n", - "\u001b[35mRUNNING AGENT: Poem Translator Agent\n", - "\u001b[1m\u001b[36m==================================================\n", - "\n", - "\u001b[31mEn la gran tapicería del tiempo y el espacio,\n", - "Un hilo de existencia teje su lugar,\n", - "Un momento fugaz, un destello de fuerza,\n", - "Una vida que arde y parpadea en la noche.\n", - "\n", - "Bailamos sobre la tierra, con pies de barro,\n", - "Buscando respuestas, de noche y de día,\n", - "Nos esforzamos y luchamos, reímos y jugamos,\n", - "Pero al final, ¿qué significa todo esto?\n", - "\n", - "Algunos dicen que es un propósito, otros dicen que es el destino,\n", - "Algunos afirman saber, mientras que otros dudan,\n", - "Pero mientras avanzamos por la puerta retorcida de la vida,\n", - "Comenzamos a ver, nuestro propio camino crear.\n", - "\n", - "Quizás el significado se encuentra, no en el final,\n", - "Sino en el viaje, el amor, el amigo,\n", - "Los días bañados por el sol, las noches estrelladas,\n", - "Los recuerdos que atesoramos, las risas, las peleas.\n", - "\n", - "O tal vez sea un misterio que nunca sabremos,\n", - "Una verdad escondida, en el resplandor del cosmos,\n", - "Un secreto que solo el universo puede compartir,\n", - "Un enigma que solo se resuelve, en el silencio que guardamos.\n", - "\n", - "Pero esto sí lo sabemos, en esta vida que vivimos,\n", - "Tenemos el poder, de sembrar la semilla,\n", - "De nutrir el crecimiento, de cuidar la tierra,\n", - "De dejar nuestra huella, de dar nuestra alegría.\n", - "\n", - "Y cuando nuestro tiempo se acabe y hayamos partido,\n", - "Nuestro legado permanece, como el sol de la mañana,\n", - "Una luz que brilla, un amor que es verdad,\n", - "Un recuerdo que vive, en los corazones de ti y de mí.\n", - "\u001b[1m\u001b[36m\n", - "==================================================\n", - "\u001b[35mRUNNING AGENT: Writer Agent\n", - "\u001b[1m\u001b[36m==================================================\n", - "\n", - "\u001b[35m\n", - "Thought: I need to write the Spanish poem into a txt file named 'poem.txt' in the current directory.\n", - "\u001b[32m\n", - "Using Tool: write_str_to_txt\n", - "\u001b[32m\n", - "Tool call dict: \n", - "{'name': 'write_str_to_txt', 'arguments': {'string_data': 'En la gran tapicería del tiempo y el espacio,\\nUn hilo de existencia teje su lugar,\\nUn momento fugaz, un destello de fuerza,\\nUna vida que arde y parpadea en la noche.\\n\\nBailamos sobre la tierra, con pies de barro,\\nBuscando respuestas, de noche y de día,\\nNos esforzamos y luchamos, reímos y jugamos,\\nPero al final, ¿qué significa todo esto?\\n\\nAlgunos dicen que es un propósito, otros dicen que es el destino,\\nAlgunos afirman saber, mientras que otros dudan,\\nPero mientras avanzamos por la puerta retorcida de la vida,\\nComenzamos a ver, nuestro propio camino crear.\\n\\nQuizás el significado se encuentra, no en el final,\\nSino en el viaje, el amor, el amigo,\\nLos días bañados por el sol, las noches estrelladas,\\nLos recuerdos que atesoramos, las risas, las peleas.\\n\\nO tal vez sea un misterio que nunca sabremos,\\nUna verdad escondida, en el resplandor del cosmos,\\nUn secreto que solo el universo puede compartir,\\nUn enigma que solo se resuelve, en el silencio que guardamos.\\n\\nPero esto sí lo sabemos, en esta vida que vivimos,\\nTenemos el poder, de sembrar la semilla,\\nDe nutrir el crecimiento, de cuidar la tierra,\\nDe dejar nuestra huella, de dar nuestra alegría.\\n\\nY cuando nuestro tiempo se acabe y hayamos partido,\\nNuestro legado permanece, como el sol de la mañana,\\nUna luz que brilla, un amor que es verdad,\\nUn recuerdo que vive, en los corazones de ti y de mí.', 'txt_filename': './poem.txt'}, 'id': 0}\n", - "Data successfully written to ./poem.txt\n", - "\u001b[32m\n", - "Tool result: \n", - "None\n", - "\u001b[34m\n", - "Observations: {0: None}\n", - "\u001b[31mThe poem has been successfully written to './poem.txt' file.\n" - ] - } - ], + "outputs": [], "source": [ "crew.run()" ] diff --git a/notebooks/planning_pattern.ipynb b/notebooks/planning_pattern.ipynb index 7e198b1..f155f17 100644 --- a/notebooks/planning_pattern.ipynb +++ b/notebooks/planning_pattern.ipynb @@ -49,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": null, "id": "056fc0ed-7ded-490b-ae0b-e7d1fd71430c", "metadata": {}, "outputs": [], @@ -108,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": null, "id": "87279781-38d4-45df-b8b5-e41c587ba38b", "metadata": {}, "outputs": [], @@ -178,7 +178,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": null, "id": "c1d3bec1-679d-4d80-bf41-bf54b00e985c", "metadata": {}, "outputs": [], @@ -246,19 +246,10 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": null, "id": "2b7e2078-9c5d-4687-8c1b-56b36a0194db", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tool name: sum_two_elements\n", - "Tool signature: {\"name\": \"sum_two_elements\", \"description\": \"\\n Computes the sum of two integers.\\n\\n Args:\\n a (int): The first integer to be summed.\\n b (int): The second integer to be summed.\\n\\n Returns:\\n int: The sum of `a` and `b`.\\n \", \"parameters\": {\"properties\": {\"a\": {\"type\": \"int\"}, \"b\": {\"type\": \"int\"}}}}\n" - ] - } - ], + "outputs": [], "source": [ "print(\"Tool name: \", sum_two_elements.name)\n", "print(\"Tool signature: \", sum_two_elements.fn_signature)" @@ -282,7 +273,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": null, "id": "b464ea29-400c-482a-83f8-d64fba727ff8", "metadata": {}, "outputs": [], @@ -292,27 +283,17 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": null, "id": "501dd7c6-3ef2-46fb-bc01-a888692b8fa5", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\"name\": \"sum_two_elements\", \"description\": \"\\n Computes the sum of two integers.\\n\\n Args:\\n a (int): The first integer to be summed.\\n b (int): The second integer to be summed.\\n\\n Returns:\\n int: The sum of `a` and `b`.\\n \", \"parameters\": {\"properties\": {\"a\": {\"type\": \"int\"}, \"b\": {\"type\": \"int\"}}}},\n", - "{\"name\": \"multiply_two_elements\", \"description\": \"\\n Multiplies two integers.\\n\\n Args:\\n a (int): The first integer to multiply.\\n b (int): The second integer to multiply.\\n\\n Returns:\\n int: The product of `a` and `b`.\\n \", \"parameters\": {\"properties\": {\"a\": {\"type\": \"int\"}, \"b\": {\"type\": \"int\"}}}},\n", - "{\"name\": \"compute_log\", \"description\": \"\\n Computes the logarithm of an integer `x` with an optional base.\\n\\n Args:\\n x (int): The integer value for which the logarithm is computed. Must be greater than 0.\\n\\n Returns:\\n float: The logarithm of `x` to the specified `base`.\\n \", \"parameters\": {\"properties\": {\"x\": {\"type\": \"int\"}}}}\n" - ] - } - ], + "outputs": [], "source": [ "print(tools_signature)" ] }, { "cell_type": "code", - "execution_count": 51, + "execution_count": null, "id": "b52ea466-79c0-4898-9c0b-69a07c2ad1db", "metadata": {}, "outputs": [], @@ -322,55 +303,10 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": null, "id": "40801b47-0021-4800-8364-9c515db1e419", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "You are a function calling AI model. You operate by running a loop with the following steps: Thought, Action, Observation.\n", - "You are provided with function signatures within XML tags.\n", - "You may call one or more functions to assist with the user query. Don' make assumptions about what values to plug\n", - "into functions. Pay special attention to the properties 'types'. You should use those types as in a Python dict.\n", - "\n", - "For each function call return a json object with function name and arguments within XML tags as follows:\n", - "\n", - "\n", - "{\"name\": ,\"arguments\": , \"id\": }\n", - "\n", - "\n", - "Here are the available tools / actions:\n", - "\n", - " \n", - "{\"name\": \"sum_two_elements\", \"description\": \"\\n Computes the sum of two integers.\\n\\n Args:\\n a (int): The first integer to be summed.\\n b (int): The second integer to be summed.\\n\\n Returns:\\n int: The sum of `a` and `b`.\\n \", \"parameters\": {\"properties\": {\"a\": {\"type\": \"int\"}, \"b\": {\"type\": \"int\"}}}},\n", - "{\"name\": \"multiply_two_elements\", \"description\": \"\\n Multiplies two integers.\\n\\n Args:\\n a (int): The first integer to multiply.\\n b (int): The second integer to multiply.\\n\\n Returns:\\n int: The product of `a` and `b`.\\n \", \"parameters\": {\"properties\": {\"a\": {\"type\": \"int\"}, \"b\": {\"type\": \"int\"}}}},\n", - "{\"name\": \"compute_log\", \"description\": \"\\n Computes the logarithm of an integer `x` with an optional base.\\n\\n Args:\\n x (int): The integer value for which the logarithm is computed. Must be greater than 0.\\n\\n Returns:\\n float: The logarithm of `x` to the specified `base`.\\n \", \"parameters\": {\"properties\": {\"x\": {\"type\": \"int\"}}}}\n", - "\n", - "\n", - "Example session:\n", - "\n", - "What's the current temperature in Madrid?\n", - "I need to get the current weather in Madrid\n", - "{\"name\": \"get_current_weather\",\"arguments\": {\"location\": \"Madrid\", \"unit\": \"celsius\"}, \"id\": 0}\n", - "\n", - "You will be called again with this:\n", - "\n", - "{0: {\"temperature\": 25, \"unit\": \"celsius\"}}\n", - "\n", - "You then output:\n", - "\n", - "The current temperature in Madrid is 25 degrees Celsius\n", - "\n", - "Additional constraints:\n", - "\n", - "- If the user asks you something unrelated to any of the tools above, answer freely enclosing your answer with tags.\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "print(REACT_SYSTEM_PROMPT)" ] @@ -385,7 +321,7 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": null, "id": "cb771338-8865-4e37-8b8b-02a949f67c41", "metadata": {}, "outputs": [], @@ -405,19 +341,10 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": null, "id": "61faa368-e936-4bf2-9a88-df2a35bb205e", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "I need to calculate the sum of two numbers, then multiply the result by a specific number, and finally calculate the logarithm of the result.\n", - "{\"name\": \"sum_two_elements\",\"arguments\": {\"a\": 1234, \"b\": 5678}, \"id\": 0}\n" - ] - } - ], + "outputs": [], "source": [ "output = GROQ_CLIENT.chat.completions.create(\n", " messages=chat_history,\n", @@ -429,7 +356,7 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": null, "id": "9514f9ab-c162-44f6-bc51-247061f811de", "metadata": {}, "outputs": [], @@ -452,7 +379,7 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": null, "id": "5a207669-3ced-43ee-8aad-c8ebf347f797", "metadata": {}, "outputs": [], @@ -462,28 +389,17 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": null, "id": "4614fe15-efa3-4111-b4e7-eb04e160f5f0", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "TagContentResult(content=['{\"name\": \"sum_two_elements\",\"arguments\": {\"a\": 1234, \"b\": 5678}, \"id\": 0}'], found=True)" - ] - }, - "execution_count": 63, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "tool_call" ] }, { "cell_type": "code", - "execution_count": 64, + "execution_count": null, "id": "3b7a6279-8cd6-4d18-8a9d-90ea04e552ed", "metadata": {}, "outputs": [], @@ -493,28 +409,17 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": null, "id": "f5835594-0105-4452-9aac-7ca76fafaf6c", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'name': 'sum_two_elements', 'arguments': {'a': 1234, 'b': 5678}, 'id': 0}" - ] - }, - "execution_count": 65, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "tool_call" ] }, { "cell_type": "code", - "execution_count": 66, + "execution_count": null, "id": "34259246-b8b6-4ae9-aa4b-1bf705fdb3d0", "metadata": {}, "outputs": [], @@ -524,7 +429,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": null, "id": "8724515b-4ba8-46a6-83fc-be472c2f1bd0", "metadata": {}, "outputs": [], @@ -534,7 +439,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": null, "id": "a8196b58-708b-4c9c-a090-eb4ad213a927", "metadata": {}, "outputs": [], @@ -557,19 +462,10 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": null, "id": "4eb27636-9080-44bd-991c-5f89f96e2675", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "I have the result of the sum, now I need to multiply it by 5.\n", - "{\"name\": \"multiply_two_elements\",\"arguments\": {\"a\": 6912, \"b\": 5}, \"id\": 1}\n" - ] - } - ], + "outputs": [], "source": [ "output = GROQ_CLIENT.chat.completions.create(\n", " messages=chat_history,\n", @@ -581,7 +477,7 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": null, "id": "34603c55-b114-4ef7-be3a-ef0148eaddb8", "metadata": {}, "outputs": [], @@ -604,7 +500,7 @@ }, { "cell_type": "code", - "execution_count": 71, + "execution_count": null, "id": "8d494dab-7e1d-44e8-a91d-685731d76864", "metadata": {}, "outputs": [], @@ -616,28 +512,17 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": null, "id": "33420c29-428e-4392-9c52-57b77d2fcc32", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "34560" - ] - }, - "execution_count": 72, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "tool_result" ] }, { "cell_type": "code", - "execution_count": 73, + "execution_count": null, "id": "0b61013e-be7a-457e-8a57-329266b29cc0", "metadata": {}, "outputs": [], @@ -647,7 +532,7 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": null, "id": "d422e9d2-773b-461a-b04b-5b0de30d59e5", "metadata": {}, "outputs": [], @@ -670,19 +555,10 @@ }, { "cell_type": "code", - "execution_count": 75, + "execution_count": null, "id": "9c5beee0-8684-4948-8e34-084dcab98eb0", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "I have the result of the multiplication, now I need to calculate its logarithm.\n", - "{\"name\": \"compute_log\",\"arguments\": {\"x\": 34560}, \"id\": 2}\n" - ] - } - ], + "outputs": [], "source": [ "output = GROQ_CLIENT.chat.completions.create(\n", " messages=chat_history,\n", @@ -694,7 +570,7 @@ }, { "cell_type": "code", - "execution_count": 76, + "execution_count": null, "id": "297ce32b-7460-477a-bd5f-2ddd8a45bf11", "metadata": {}, "outputs": [], @@ -717,7 +593,7 @@ }, { "cell_type": "code", - "execution_count": 77, + "execution_count": null, "id": "97eeb277-1486-4d8f-8441-8adbde84389e", "metadata": {}, "outputs": [], @@ -729,28 +605,17 @@ }, { "cell_type": "code", - "execution_count": 78, + "execution_count": null, "id": "d77818e5-ae29-42d4-8c6e-4527bcf56959", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10.450452222917992" - ] - }, - "execution_count": 78, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "tool_result" ] }, { "cell_type": "code", - "execution_count": 79, + "execution_count": null, "id": "694284bb-64de-4f48-b0e2-c870b129a225", "metadata": {}, "outputs": [], @@ -760,7 +625,7 @@ }, { "cell_type": "code", - "execution_count": 80, + "execution_count": null, "id": "c26c8ae7-a6f3-4d8c-b509-fb39054684bf", "metadata": {}, "outputs": [], @@ -783,18 +648,10 @@ }, { "cell_type": "code", - "execution_count": 81, + "execution_count": null, "id": "d7faf46c-2ee2-4f40-b371-7a42a8885e8f", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The result of the calculation is a logarithm of approximately 10.45\n" - ] - } - ], + "outputs": [], "source": [ "output = GROQ_CLIENT.chat.completions.create(\n", " messages=chat_history,\n", diff --git a/notebooks/reflection_pattern.ipynb b/notebooks/reflection_pattern.ipynb index 31b6241..5b55b1b 100644 --- a/notebooks/reflection_pattern.ipynb +++ b/notebooks/reflection_pattern.ipynb @@ -61,7 +61,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "96731d2f-a079-4e41-9756-220f02d4ebd8", "metadata": {}, "outputs": [], @@ -89,7 +89,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "12467256-c741-495a-9923-439c1fcf270d", "metadata": {}, "outputs": [], @@ -114,7 +114,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "0742e7bd-4857-4ed1-a96b-37098d448bdd", "metadata": {}, "outputs": [], @@ -137,7 +137,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "ff984277-733c-4495-b7fd-0669393380b8", "metadata": {}, "outputs": [], @@ -157,77 +157,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "c03f208b-2234-4fd1-a02b-f4fff06c01a6", "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "Here is a Python implementation of the Merge Sort algorithm:\n", - "```\n", - "def merge_sort(arr):\n", - " \"\"\"\n", - " Sorts an array using the Merge Sort algorithm.\n", - "\n", - " Time complexity: O(n log n)\n", - " Space complexity: O(n)\n", - "\n", - " :param arr: the array to be sorted\n", - " :return: the sorted array\n", - " \"\"\"\n", - " if len(arr) <= 1:\n", - " return arr\n", - "\n", - " mid = len(arr) // 2\n", - " left = arr[:mid]\n", - " right = arr[mid:]\n", - "\n", - " left = merge_sort(left)\n", - " right = merge_sort(right)\n", - "\n", - " return merge(left, right)\n", - "\n", - "\n", - "def merge(left, right):\n", - " \"\"\"\n", - " Merges two sorted arrays into a single sorted array.\n", - "\n", - " :param left: the first sorted array\n", - " :param right: the second sorted array\n", - " :return: the merged sorted array\n", - " \"\"\"\n", - " result = []\n", - " i = j = 0\n", - "\n", - " while i < len(left) and j < len(right):\n", - " if left[i] <= right[j]:\n", - " result.append(left[i])\n", - " i += 1\n", - " else:\n", - " result.append(right[j])\n", - " j += 1\n", - "\n", - " result.extend(left[i:])\n", - " result.extend(right[j:])\n", - "\n", - " return result\n", - "```\n", - "Here's an explanation of the code:\n", - "\n", - "The `merge_sort` function takes an array as input and recursively divides it into two halves until each half has a length of 1 or less. Then, it merges the two halves using the `merge` function.\n", - "\n", - "The `merge` function takes two sorted arrays as input and merges them into a single sorted array. It does this by comparing elements from each array and adding the smaller element to the result array. If one array is exhausted, it adds the remaining elements from the other array to the result.\n", - "\n", - "Note that this implementation has a time complexity of O(n log n) and a space complexity of O(n), making it an efficient sorting algorithm for large datasets.\n", - "\n", - "Do you have any feedback or would you like me to revise anything?" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display_markdown(mergesort_code, raw=True)" ] @@ -262,7 +195,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "9d93c928-d585-48af-a74c-a5b8d84593c6", "metadata": { "tags": [] @@ -287,7 +220,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "26af1a73-4d91-40e8-a9bc-c34d32b2ab82", "metadata": { "tags": [] @@ -312,7 +245,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "40fee42f-d47a-41b1-a40d-7208ba76ce98", "metadata": { "tags": [] @@ -327,84 +260,12 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "0fef3203-c7f1-407f-8b9b-4e8ae140a4cb", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "text/markdown": [ - "Overall, your implementation of the Merge Sort algorithm is correct and well-documented. Here are some minor suggestions for improvement:\n", - "\n", - "1. **Docstrings:** Your docstrings are excellent, but you might consider adding a `:rtype:` specification to indicate the return type of each function. For example, `:rtype: list` would indicate that the function returns a list.\n", - "\n", - "2. **Type Hints:** Adding type hints for function parameters and return types can improve code readability and help with static type checking. For example, `def merge_sort(arr: list) -> list:` would indicate that the function takes a list as input and returns a list.\n", - "\n", - "3. **Error Handling:** Your implementation assumes that the input array only contains comparable elements (e.g., integers or strings). However, if the input array contains uncomparable elements (e.g., a mix of integers and strings), your implementation will raise a `TypeError`. You might consider adding error handling to handle such cases.\n", - "\n", - "4. **Code Organization:** Your code is well-organized, but you might consider moving the `merge` function inside the `merge_sort` function as a nested function. This would emphasize that the `merge` function is a helper function for the `merge_sort` function and is not intended to be used independently.\n", - "\n", - "Here is the revised code incorporating these suggestions:\n", - "\n", - "```\n", - "def merge_sort(arr: list) -> list:\n", - " \"\"\"\n", - " Sorts an array using the Merge Sort algorithm.\n", - "\n", - " Time complexity: O(n log n)\n", - " Space complexity: O(n)\n", - "\n", - " :param arr: the array to be sorted\n", - " :return: the sorted array\n", - " :rtype: list\n", - " \"\"\"\n", - " if len(arr) <= 1:\n", - " return arr\n", - "\n", - " def merge(left: list, right: list) -> list:\n", - " \"\"\"\n", - " Merges two sorted arrays into a single sorted array.\n", - "\n", - " :param left: the first sorted array\n", - " :param right: the second sorted array\n", - " :return: the merged sorted array\n", - " :rtype: list\n", - " \"\"\"\n", - " result = []\n", - " i = j = 0\n", - "\n", - " while i < len(left) and j < len(right):\n", - " if left[i] <= right[j]:\n", - " result.append(left[i])\n", - " i += 1\n", - " else:\n", - " result.append(right[j])\n", - " j += 1\n", - "\n", - " result.extend(left[i:])\n", - " result.extend(right[j:])\n", - "\n", - " return result\n", - "\n", - " mid = len(arr) // 2\n", - " left = arr[:mid]\n", - " right = arr[mid:]\n", - "\n", - " left = merge_sort(left)\n", - " right = merge_sort(right)\n", - "\n", - " return merge(left, right)\n", - "```\n", - "\n", - "Overall, your implementation is well-written and easy to understand. With these minor suggestions, it's even better!" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display_markdown(critique, raw=True)" ] @@ -419,7 +280,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "27a85bb3-cf6a-4576-8caf-cd41e602a1f1", "metadata": { "tags": [] @@ -444,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "91d845cf-51c3-4cfd-b6a7-1b970413f6db", "metadata": { "tags": [] @@ -459,84 +320,12 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "ef14eaa8-f501-4efc-997f-8564ec8dccd8", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "text/markdown": [ - "Thank you for the feedback! I'm glad to hear that my implementation is correct and well-documented. Your suggestions are excellent and I've incorporated them into the revised code.\n", - "\n", - "Here's the revised code with the suggested improvements:\n", - "\n", - "```\n", - "def merge_sort(arr: list) -> list:\n", - " \"\"\"\n", - " Sorts an array using the Merge Sort algorithm.\n", - "\n", - " Time complexity: O(n log n)\n", - " Space complexity: O(n)\n", - "\n", - " :param arr: the array to be sorted\n", - " :return: the sorted array\n", - " :rtype: list\n", - " \"\"\"\n", - " if len(arr) <= 1:\n", - " return arr\n", - "\n", - " def merge(left: list, right: list) -> list:\n", - " \"\"\"\n", - " Merges two sorted arrays into a single sorted array.\n", - "\n", - " :param left: the first sorted array\n", - " :param right: the second sorted array\n", - " :return: the merged sorted array\n", - " :rtype: list\n", - " \"\"\"\n", - " result = []\n", - " i = j = 0\n", - "\n", - " while i < len(left) and j < len(right):\n", - " if left[i] <= right[j]:\n", - " result.append(left[i])\n", - " i += 1\n", - " else:\n", - " result.append(right[j])\n", - " j += 1\n", - "\n", - " result.extend(left[i:])\n", - " result.extend(right[j:])\n", - "\n", - " return result\n", - "\n", - " try:\n", - " mid = len(arr) // 2\n", - " left = arr[:mid]\n", - " right = arr[mid:]\n", - "\n", - " left = merge_sort(left)\n", - " right = merge_sort(right)\n", - "\n", - " return merge(left, right)\n", - " except TypeError:\n", - " raise ValueError(\"The input array must contain comparable elements\")\n", - "\n", - "```\n", - "\n", - "I've added type hints for function parameters and return types, as well as `:rtype:` specifications in the docstrings. I've also moved the `merge` function inside the `merge_sort` function as a nested function, which emphasizes its role as a helper function.\n", - "\n", - "Regarding error handling, I've added a `try-except` block to catch `TypeError` exceptions that occur when the input array contains uncomparable elements. In such cases, the function raises a `ValueError` with a more informative error message.\n", - "\n", - "Thank you again for your feedback! I'm committed to writing high-quality Python code, and your suggestions have helped me improve my implementation of the Merge Sort algorithm." - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display_markdown(essay, raw=True)" ] @@ -577,7 +366,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "3f904241-29a1-4519-b6ab-15be0a7cfc53", "metadata": {}, "outputs": [], @@ -587,7 +376,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "dd1a8071-c763-4dbf-8db7-60f9116f62e8", "metadata": {}, "outputs": [], @@ -597,7 +386,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "87c8cf16-0dfa-49b6-bc30-8f14bbe7860a", "metadata": {}, "outputs": [], @@ -611,390 +400,10 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "6a9a3e5b-9b45-4a27-b391-f78b57ff94f1", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1m\u001b[36m\n", - "==================================================\n", - "\u001b[35mSTEP 1/10\n", - "\u001b[1m\u001b[36m==================================================\n", - "\n", - "\u001b[34m \n", - "\n", - "GENERATION\n", - "\n", - " **Merge Sort Algorithm Implementation in Python**\n", - "=====================================================\n", - "\n", - "### Overview\n", - "\n", - "Merge sort is a divide-and-conquer algorithm that splits a given list into two halves, recursively sorts each half, and then merges the two sorted halves.\n", - "\n", - "### Code\n", - "\n", - "```python\n", - "def merge_sort(arr):\n", - " \"\"\"\n", - " Sorts a given list using the Merge Sort algorithm.\n", - "\n", - " Args:\n", - " arr (list): The list to be sorted.\n", - "\n", - " Returns:\n", - " list: The sorted list.\n", - " \"\"\"\n", - "\n", - " # Base case: If the list has 1 or fewer elements, it's already sorted.\n", - " if len(arr) <= 1:\n", - " return arr\n", - "\n", - " # Find the middle index of the list.\n", - " mid = len(arr) // 2\n", - "\n", - " # Divide the list into two halves.\n", - " left_half = arr[:mid]\n", - " right_half = arr[mid:]\n", - "\n", - " # Recursively sort each half.\n", - " left_half = merge_sort(left_half)\n", - " right_half = merge_sort(right_half)\n", - "\n", - " # Merge the two sorted halves.\n", - " return merge(left_half, right_half)\n", - "\n", - "\n", - "def merge(left, right):\n", - " \"\"\"\n", - " Merges two sorted lists into a single sorted list.\n", - "\n", - " Args:\n", - " left (list): The first sorted list.\n", - " right (list): The second sorted list.\n", - "\n", - " Returns:\n", - " list: The merged sorted list.\n", - " \"\"\"\n", - "\n", - " # Initialize the merged list and index counters.\n", - " merged = []\n", - " left_index = 0\n", - " right_index = 0\n", - "\n", - " # Merge smaller elements first.\n", - " while left_index < len(left) and right_index < len(right):\n", - " if left[left_index] <= right[right_index]:\n", - " merged.append(left[left_index])\n", - " left_index += 1\n", - " else:\n", - " merged.append(right[right_index])\n", - " right_index += 1\n", - "\n", - " # Append any remaining elements from the left or right lists.\n", - " merged.extend(left[left_index:])\n", - " merged.extend(right[right_index:])\n", - "\n", - " return merged\n", - "\n", - "\n", - "### Example Usage\n", - "\n", - "```python\n", - "# Create a sample unsorted list.\n", - "arr = [64, 34, 25, 12, 22, 11, 90]\n", - "\n", - "# Sort the list using Merge Sort.\n", - "sorted_arr = merge_sort(arr)\n", - "\n", - "print(\"Original List:\", arr)\n", - "print(\"Sorted List:\", sorted_arr)\n", - "```\n", - "\n", - "This implementation provides a clear and efficient implementation of the Merge Sort algorithm. The `merge_sort` function divides the list into two halves, recursively sorts each half, and then merges the two sorted halves using the `merge` function. The `merge` function takes two sorted lists and merges them into a single sorted list.\n", - "\n", - "Note that this implementation has a time complexity of O(n log n) and a space complexity of O(n), making it suitable for large datasets.\n", - "\u001b[32m \n", - "\n", - "REFLECTION\n", - "\n", - " **Review and Recommendations**\n", - "\n", - "**Overall Assessment**\n", - "\n", - "The provided code is well-structured, easy to understand, and correctly implements the Merge Sort algorithm. However, there are a few areas that can be improved for better performance, readability, and robustness.\n", - "\n", - "**Review**\n", - "\n", - "1. **Type Hints**: The code does not use type hints for function arguments and return types. Adding type hints can improve code readability and facilitate static type checking.\n", - "\n", - "2. **Docstrings**: While the code includes docstrings for functions, they can be improved by providing more details about the function's behavior and edge cases. For example, the `merge_sort` function should mention that the input list is modified in-place.\n", - "\n", - "3. **Error Handling**: The code does not handle errors that may occur when sorting non-comparable elements or when receiving non-list inputs. Adding error handling can make the code more robust.\n", - "\n", - "4. **Consistent Naming**: The variable `mid` uses lowercase and underscore, but `left_half` and `right_half` are camelCase. Python's PEP 8 recommends using lowercase with underscores for variable names.\n", - "\n", - "5. **Magic Numbers**: The code uses the magic number 1 in the `merge_sort` function. While this number is not likely to change, it's better to use a named constant to improve code readability.\n", - "\n", - "**Recommendations**\n", - "\n", - "1. **Use Type Hints**\n", - "\n", - " ```python\n", - "def merge_sort(arr: list) -> list:\n", - " ...\n", - "```\n", - "\n", - "2. **Improve Docstrings**\n", - "\n", - " ```python\n", - "def merge_sort(arr: list) -> list:\n", - " \"\"\"\n", - " Sorts a given list using the Merge Sort algorithm.\n", - "\n", - " This function modifies the input list in-place. If the input list contains non-comparable elements,\n", - " a TypeError is raised.\n", - "\n", - " Args:\n", - " arr (list): The list to be sorted.\n", - "\n", - " Returns:\n", - " list: The sorted list.\n", - "\n", - " Raises:\n", - " TypeError: If the input list contains non-comparable elements.\n", - " \"\"\"\n", - " ...\n", - "```\n", - "\n", - "3. **Add Error Handling**\n", - "\n", - " ```python\n", - "def merge_sort(arr: list) -> list:\n", - " if not isinstance(arr, list):\n", - " raise TypeError(\"Input must be a list\")\n", - "\n", - " try:\n", - " # Base case: If the list has 1 or fewer elements, it's already sorted.\n", - " ...\n", - " except TypeError as e:\n", - " raise TypeError(\"Input list contains non-comparable elements\") from e\n", - "```\n", - "\n", - "4. **Use Consistent Naming**\n", - "\n", - " ```python\n", - "# Divide the list into two halves.\n", - "left_half_list = arr[:mid]\n", - "right_half_list = arr[mid:]\n", - "```\n", - "\n", - "5. **Avoid Magic Numbers**\n", - "\n", - " ```python\n", - "MIN_ELEMENTS = 1\n", - "\n", - "# Base case: If the list has MIN_ELEMENTS or fewer elements, it's already sorted.\n", - "if len(arr) <= MIN_ELEMENTS:\n", - " return arr\n", - "```\n", - "\n", - "**Additional Suggestion**\n", - "\n", - "The `merge` function can be simplified by using a list comprehension with a conditional expression. While this change does not significantly impact performance or readability, it can make the code more concise.\n", - "\n", - "```python\n", - "def merge(left: list, right: list) -> list:\n", - " \"\"\"\n", - " Merges two sorted lists into a single sorted list.\n", - "\n", - " Args:\n", - " left (list): The first sorted list.\n", - " right (list): The second sorted list.\n", - "\n", - " Returns:\n", - " list: The merged sorted list.\n", - " \"\"\"\n", - " merged = []\n", - " left_index = 0\n", - " right_index = 0\n", - "\n", - " while left_index < len(left) and right_index < len(right):\n", - " if left[left_index] <= right[right_index]:\n", - " merged.append(left[left_index])\n", - " left_index += 1\n", - " else:\n", - " merged.append(right[right_index])\n", - " right_index += 1\n", - "\n", - " # Simplified implementation using list comprehension with a conditional expression.\n", - " merged.extend([x for sublist in [left[left_index:], right[right_index:]] for x in sublist])\n", - " return merged\n", - "```\n", - "\u001b[1m\u001b[36m\n", - "==================================================\n", - "\u001b[35mSTEP 2/10\n", - "\u001b[1m\u001b[36m==================================================\n", - "\n", - "\u001b[34m \n", - "\n", - "GENERATION\n", - "\n", - " **Revised Merge Sort Implementation in Python**\n", - "=============================================\n", - "\n", - "### Overview\n", - "\n", - "This revised implementation of the Merge Sort algorithm incorporates the suggested improvements for better performance, readability, and robustness. The code includes type hints, improved docstrings, error handling, consistent naming conventions, and avoids magic numbers.\n", - "\n", - "### Code\n", - "\n", - "```python\n", - "MIN_ELEMENTS = 1\n", - "\n", - "def merge_sort(arr: list) -> list:\n", - " \"\"\"\n", - " Sorts a given list using the Merge Sort algorithm.\n", - "\n", - " This function modifies the input list in-place. If the input list contains non-comparable elements,\n", - " a TypeError is raised.\n", - "\n", - " Args:\n", - " arr (list): The list to be sorted.\n", - "\n", - " Returns:\n", - " list: The sorted list.\n", - "\n", - " Raises:\n", - " TypeError: If the input list contains non-comparable elements or if the input is not a list.\n", - " \"\"\"\n", - "\n", - " if not isinstance(arr, list):\n", - " raise TypeError(\"Input must be a list\")\n", - "\n", - " try:\n", - " # Base case: If the list has MIN_ELEMENTS or fewer elements, it's already sorted.\n", - " if len(arr) <= MIN_ELEMENTS:\n", - " return arr\n", - "\n", - " # Find the middle index of the list.\n", - " mid = len(arr) // 2\n", - "\n", - " # Divide the list into two halves.\n", - " left_half_list = arr[:mid]\n", - " right_half_list = arr[mid:]\n", - "\n", - " # Recursively sort each half.\n", - " left_half_list = merge_sort(left_half_list)\n", - " right_half_list = merge_sort(right_half_list)\n", - "\n", - " # Merge the two sorted halves.\n", - " return merge(left_half_list, right_half_list)\n", - " except TypeError as e:\n", - " raise TypeError(\"Input list contains non-comparable elements\") from e\n", - "\n", - "\n", - "def merge(left: list, right: list) -> list:\n", - " \"\"\"\n", - " Merges two sorted lists into a single sorted list.\n", - "\n", - " Args:\n", - " left (list): The first sorted list.\n", - " right (list): The second sorted list.\n", - "\n", - " Returns:\n", - " list: The merged sorted list.\n", - " \"\"\"\n", - " merged = []\n", - " left_index = 0\n", - " right_index = 0\n", - "\n", - " while left_index < len(left) and right_index < len(right):\n", - " if left[left_index] <= right[right_index]:\n", - " merged.append(left[left_index])\n", - " left_index += 1\n", - " else:\n", - " merged.append(right[right_index])\n", - " right_index += 1\n", - "\n", - " # Simplified implementation using list comprehension with a conditional expression.\n", - " merged.extend([x for sublist in [left[left_index:], right[right_index:]] for x in sublist])\n", - " return merged\n", - "\n", - "\n", - "### Example Usage\n", - "\n", - "# Create a sample unsorted list.\n", - "arr = [64, 34, 25, 12, 22, 11, 90]\n", - "\n", - "# Sort the list using Merge Sort.\n", - "sorted_arr = merge_sort(arr)\n", - "\n", - "print(\"Original List:\", arr)\n", - "print(\"Sorted List:\", sorted_arr)\n", - "\n", - "```\n", - "\n", - "This revised implementation provides a more robust and maintainable implementation of the Merge Sort algorithm. It includes type hints, improved docstrings, error handling, consistent naming conventions, and avoids magic numbers, making the code easier to understand and modify.\n", - "\u001b[32m \n", - "\n", - "REFLECTION\n", - "\n", - " **Review and Recommendations**\n", - "\n", - "The revised implementation of the Merge Sort algorithm has significantly improved in terms of readability, maintainability, and robustness. The code adheres to Python's PEP 8 guidelines, includes type hints, and provides clear docstrings. Error handling has also been improved to handle potential issues with non-comparable elements and non-list inputs.\n", - "\n", - "**No Critiques or Recommendations**\n", - "\n", - "Based on the revised code, there are no major critiques or recommendations to be made. The code is well-structured, follows best practices, and effectively implements the Merge Sort algorithm.\n", - "\n", - "However, it's worth noting that the `merge` function can be further simplified by using a more Pythonic way of merging the two sorted lists. Instead of using a list comprehension with a conditional expression, you can use the `+` operator to concatenate the remaining elements.\n", - "\n", - "```python\n", - "def merge(left: list, right: list) -> list:\n", - " \"\"\"\n", - " Merges two sorted lists into a single sorted list.\n", - "\n", - " Args:\n", - " left (list): The first sorted list.\n", - " right (list): The second sorted list.\n", - "\n", - " Returns:\n", - " list: The merged sorted list.\n", - " \"\"\"\n", - " merged = []\n", - " left_index = 0\n", - " right_index = 0\n", - "\n", - " while left_index < len(left) and right_index < len(right):\n", - " if left[left_index] <= right[right_index]:\n", - " merged.append(left[left_index])\n", - " left_index += 1\n", - " else:\n", - " merged.append(right[right_index])\n", - " right_index += 1\n", - "\n", - " # Simplified implementation using the + operator.\n", - " merged.extend(left[left_index:] + right[right_index:])\n", - " return merged\n", - "```\n", - "\n", - "**Conclusion**\n", - "\n", - "Overall, the revised implementation of the Merge Sort algorithm is of high quality and meets the standards for maintainable and readable code. The minor suggestion for further simplifying the `merge` function is provided as a note, but the code is already in a good state.\n", - "\n", - "****\n", - "\u001b[31m \n", - "\n", - "Stop Sequence found. Stopping the reflection loop ... \n", - "\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "final_response = agent.run(\n", " user_msg=user_msg,\n", @@ -1015,115 +424,10 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "6e4663cd-61dd-4a38-866a-f032045a444a", "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "**Revised Merge Sort Implementation in Python**\n", - "=============================================\n", - "\n", - "### Overview\n", - "\n", - "This revised implementation of the Merge Sort algorithm incorporates the suggested improvements for better performance, readability, and robustness. The code includes type hints, improved docstrings, error handling, consistent naming conventions, and avoids magic numbers.\n", - "\n", - "### Code\n", - "\n", - "```python\n", - "MIN_ELEMENTS = 1\n", - "\n", - "def merge_sort(arr: list) -> list:\n", - " \"\"\"\n", - " Sorts a given list using the Merge Sort algorithm.\n", - "\n", - " This function modifies the input list in-place. If the input list contains non-comparable elements,\n", - " a TypeError is raised.\n", - "\n", - " Args:\n", - " arr (list): The list to be sorted.\n", - "\n", - " Returns:\n", - " list: The sorted list.\n", - "\n", - " Raises:\n", - " TypeError: If the input list contains non-comparable elements or if the input is not a list.\n", - " \"\"\"\n", - "\n", - " if not isinstance(arr, list):\n", - " raise TypeError(\"Input must be a list\")\n", - "\n", - " try:\n", - " # Base case: If the list has MIN_ELEMENTS or fewer elements, it's already sorted.\n", - " if len(arr) <= MIN_ELEMENTS:\n", - " return arr\n", - "\n", - " # Find the middle index of the list.\n", - " mid = len(arr) // 2\n", - "\n", - " # Divide the list into two halves.\n", - " left_half_list = arr[:mid]\n", - " right_half_list = arr[mid:]\n", - "\n", - " # Recursively sort each half.\n", - " left_half_list = merge_sort(left_half_list)\n", - " right_half_list = merge_sort(right_half_list)\n", - "\n", - " # Merge the two sorted halves.\n", - " return merge(left_half_list, right_half_list)\n", - " except TypeError as e:\n", - " raise TypeError(\"Input list contains non-comparable elements\") from e\n", - "\n", - "\n", - "def merge(left: list, right: list) -> list:\n", - " \"\"\"\n", - " Merges two sorted lists into a single sorted list.\n", - "\n", - " Args:\n", - " left (list): The first sorted list.\n", - " right (list): The second sorted list.\n", - "\n", - " Returns:\n", - " list: The merged sorted list.\n", - " \"\"\"\n", - " merged = []\n", - " left_index = 0\n", - " right_index = 0\n", - "\n", - " while left_index < len(left) and right_index < len(right):\n", - " if left[left_index] <= right[right_index]:\n", - " merged.append(left[left_index])\n", - " left_index += 1\n", - " else:\n", - " merged.append(right[right_index])\n", - " right_index += 1\n", - "\n", - " # Simplified implementation using list comprehension with a conditional expression.\n", - " merged.extend([x for sublist in [left[left_index:], right[right_index:]] for x in sublist])\n", - " return merged\n", - "\n", - "\n", - "### Example Usage\n", - "\n", - "# Create a sample unsorted list.\n", - "arr = [64, 34, 25, 12, 22, 11, 90]\n", - "\n", - "# Sort the list using Merge Sort.\n", - "sorted_arr = merge_sort(arr)\n", - "\n", - "print(\"Original List:\", arr)\n", - "print(\"Sorted List:\", sorted_arr)\n", - "\n", - "```\n", - "\n", - "This revised implementation provides a more robust and maintainable implementation of the Merge Sort algorithm. It includes type hints, improved docstrings, error handling, consistent naming conventions, and avoids magic numbers, making the code easier to understand and modify." - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display_markdown(final_response, raw=True)" ] @@ -1131,7 +435,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, diff --git a/notebooks/tool_pattern.ipynb b/notebooks/tool_pattern.ipynb index 241098d..7d31b78 100644 --- a/notebooks/tool_pattern.ipynb +++ b/notebooks/tool_pattern.ipynb @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "1c851271-9b5a-4b48-a0e0-bf889cfb303b", "metadata": {}, "outputs": [], @@ -79,21 +79,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "3f52e61e-be31-4e6f-9f4f-eeb7082ad827", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'{\"temperature\": 25, \"unit\": \"celsius\"}'" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "get_current_weather(location=\"Madrid\", unit=\"celsius\")" ] @@ -181,7 +170,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "692b5c16-77f3-4de0-b2b5-16bfc5812b7b", "metadata": {}, "outputs": [], @@ -238,20 +227,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "e00b09e8-55d3-4a59-a9cf-29329af78d9a", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "{\"id\": 0, \"name\": \"get_current_weather\", \"arguments\": {\"location\": \"Madrid\", \"unit\": \"celsius\"}}\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "tool_chat_history = [\n", " {\n", @@ -296,7 +275,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "4366ae38-055a-45ec-937b-dfec7eaad00b", "metadata": {}, "outputs": [], @@ -317,23 +296,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "c5890ba4-3f2f-4dc8-9a62-dff0079f07bb", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'id': 0,\n", - " 'name': 'get_current_weather',\n", - " 'arguments': {'location': 'Madrid', 'unit': 'celsius'}}" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "parsed_output = parse_tool_call_str(output)\n", "parsed_output" @@ -349,7 +315,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "169f06bb-836d-4270-bd66-abc2aadc0757", "metadata": {}, "outputs": [], @@ -359,21 +325,10 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "ecdfbbc5-7cdf-4c21-8b75-055446658675", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'{\"temperature\": 25, \"unit\": \"celsius\"}'" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "result" ] @@ -390,7 +345,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "3fb0fc08-dad9-42cd-a2a9-674b8191d06b", "metadata": {}, "outputs": [], @@ -403,21 +358,10 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "b610fb1f-24af-4cc1-b485-fa0c5bfca846", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'The current temperature in Madrid is 25 degrees Celsius.'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "GROQ_CLIENT.chat.completions.create(\n", " messages=agent_chat_history,\n", @@ -466,7 +410,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "b9413902-e3ea-4c0a-bfd2-180d69ba5cd1", "metadata": {}, "outputs": [], @@ -528,30 +472,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "aad2bbed-549e-4c0e-91fd-37b4694e0b50", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[{'title': 'HPy – A better C API for Python',\n", - " 'url': 'https://hpyproject.org/'},\n", - " {'title': 'Fuzzing 101',\n", - " 'url': 'https://github.com/antonio-morales/Fuzzing101'},\n", - " {'title': \"Arthur Whitney's one liner sudoku solver (2011)\",\n", - " 'url': 'https://dfns.dyalog.com/n_sudoku.htm'},\n", - " {'title': 'Pine martens return to Dartmoor after 150-year absence',\n", - " 'url': 'https://www.theguardian.com/uk-news/2024/oct/01/pine-martens-return-to-dartmoor-after-150-year-absence'},\n", - " {'title': 'Gokapi: Lightweight selfhosted Firefox Send alternative with AWS S3 support',\n", - " 'url': 'https://github.com/Forceu/Gokapi'}]" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "json.loads(fetch_top_hacker_news_stories(top_n=5))" ] @@ -566,7 +490,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "4616e412-d4a8-4fe5-bcb1-dd00ce48640a", "metadata": {}, "outputs": [], @@ -584,21 +508,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "df16bfa5-0ed4-46e1-b262-006f36fb8e78", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'fetch_top_hacker_news_stories'" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "hn_tool.name" ] @@ -613,23 +526,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "e0da95e0-10a8-4d17-aae7-ed3cc20abb03", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'name': 'fetch_top_hacker_news_stories',\n", - " 'description': '\\n Fetch the top stories from Hacker News.\\n\\n This function retrieves the top `top_n` stories from Hacker News using the Hacker News API. \\n Each story contains the title, URL, score, author, and time of submission. The data is fetched \\n from the official Firebase Hacker News API, which returns story details in JSON format.\\n\\n Args:\\n top_n (int): The number of top stories to retrieve.\\n ',\n", - " 'parameters': {'properties': {'top_n': {'type': 'int'}}}}" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "json.loads(hn_tool.fn_signature)" ] @@ -660,7 +560,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "4a303211-f2a6-43c0-85aa-081fb0be2bbe", "metadata": {}, "outputs": [], @@ -678,7 +578,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "92c706fd-0a4b-46be-bbb3-c02618dbf677", "metadata": {}, "outputs": [], @@ -688,18 +588,10 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "be02a976-1e72-40ad-9ada-460148ca65d1", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "I don't have a personal name. I am an AI assistant designed to provide information and assist with tasks.\n" - ] - } - ], + "outputs": [], "source": [ "print(output)" ] @@ -714,48 +606,20 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "b74bbc64-8943-4ae3-9928-6230ead61e77", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[32m\n", - "Using Tool: fetch_top_hacker_news_stories\n", - "\u001b[32m\n", - "Tool call dict: \n", - "{'id': 0, 'name': 'fetch_top_hacker_news_stories', 'arguments': {'top_n': 5}}\n", - "\u001b[32m\n", - "Tool result: \n", - "[{\"title\": \"HPy \\u2013 A better C API for Python\", \"url\": \"https://hpyproject.org/\"}, {\"title\": \"Fuzzing 101\", \"url\": \"https://github.com/antonio-morales/Fuzzing101\"}, {\"title\": \"Arthur Whitney's one liner sudoku solver (2011)\", \"url\": \"https://dfns.dyalog.com/n_sudoku.htm\"}, {\"title\": \"Pine martens return to Dartmoor after 150-year absence\", \"url\": \"https://www.theguardian.com/uk-news/2024/oct/01/pine-martens-return-to-dartmoor-after-150-year-absence\"}, {\"title\": \"Gokapi: Lightweight selfhosted Firefox Send alternative with AWS S3 support\", \"url\": \"https://github.com/Forceu/Gokapi\"}]\n" - ] - } - ], + "outputs": [], "source": [ "output = tool_agent.run(user_msg=\"Tell me the top 5 Hacker News stories right now\")" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "53476bff-812d-4e56-afb9-de21474f6580", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Here are the top 5 Hacker News stories right now:\n", - "1. [HPy – A better C API for Python](https://hpyproject.org/)\n", - "2. [Fuzzing 101](https://github.com/antonio-morales/Fuzzing101)\n", - "3. [Arthur Whitney's one liner sudoku solver (2011)](https://dfns.dyalog.com/n_sudoku.htm)\n", - "4. [Pine martens return to Dartmoor after 150-year absence](https://www.theguardian.com/uk-news/2024/oct/01/pine-martens-return-to-dartmoor-after-150-year-absence)\n", - "5. [Gokapi: Lightweight selfhosted Firefox Send alternative with AWS S3 support](https://github.com/Forceu/Gokapi)\n" - ] - } - ], + "outputs": [], "source": [ "print(output)" ] From 7271e7395aafa080304ffc637cddede0d35aff8d Mon Sep 17 00:00:00 2001 From: MichaelisTrofficus Date: Thu, 24 Oct 2024 16:49:45 +0200 Subject: [PATCH 5/6] add Groq API Key section to readme --- README.md | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e8c15a7..25e6edb 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ - [2. The 4 Agentic Patterns](#the-4-agentic-patterns) - [3. Installation](#installation) -- [4. Usage](#usage) - - [4.1 Using a Reflection Agent - Reflection Pattern](#using-a-reflection-agent---reflection-pattern) - - [4.2 Creating and Using Tools - Tool Use Pattern](#creating-and-using-tools---tool-use-pattern) - - [4.3 Reasoning with a ReAct Agent - Planning Pattern](#reasoning-with-a-react-agent---planning-pattern) - - [4.4 Defining and running a Crew of Agents - MultiAgent Pattern](#defining-and-running-a-crew-of-agents---multiagent-pattern) -- [5. Recommended Workflow](#recommended-workflow) -- [6. Star History](#star-history) +- [4. Groq API Key](#groq-api-key) +- [5. Usage](#usage) + - [5.1 Using a Reflection Agent - Reflection Pattern](#using-a-reflection-agent---reflection-pattern) + - [5.2 Creating and Using Tools - Tool Use Pattern](#creating-and-using-tools---tool-use-pattern) + - [5.3 Reasoning with a ReAct Agent - Planning Pattern](#reasoning-with-a-react-agent---planning-pattern) + - [5.4 Defining and running a Crew of Agents - MultiAgent Pattern](#defining-and-running-a-crew-of-agents---multiagent-pattern) +- [6. Recommended Workflow](#recommended-workflow) +- [7. Star History](#star-history) ## Introduction @@ -174,9 +175,19 @@ pip install -U agentic-patterns --- +## Groq API Key + +This project works with [Groq](https://groq.com/) as the LLM provider, so you'll need to create an API Key in this platform. + +When you have your API Key copy and paste it in an `.env` file. + +The content of this `.env` file should match the structure of the `.env.example` I've created in the repo, but instead of an empty string, the `GROQ_API_KEY` var will contain your API Key. + +--- + ## Usage -Once you have the library installed, you can start playing with the 4 patterns implementation (I'll encourage you to take a look at the code, to fully understand what is happening under the hood). +Once you have both library installed and the `.env` file created, you can start playing with the 4 patterns implementation (I'll encourage you to take a look at the code, to fully understand what is happening under the hood). Let's see an example of how to put the 4 patterns into practise. From 88602f4c5a1270220def2c93a9a480ae60dba18f Mon Sep 17 00:00:00 2001 From: MichaelisTrofficus Date: Thu, 24 Oct 2024 16:51:20 +0200 Subject: [PATCH 6/6] bump to 1.0.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bec0e55..f9d3653 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "agentic-patterns" -version = "0.2.0" +version = "1.0.0" description = "" authors = ["MichaelisTrofficus "] license = "MIT"