diff --git a/docs/docs/how-tos/autogen-integration.ipynb b/docs/docs/how-tos/autogen-integration.ipynb new file mode 100644 index 000000000..1673014d4 --- /dev/null +++ b/docs/docs/how-tos/autogen-integration.ipynb @@ -0,0 +1,334 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "100c0c81-6a9f-4ba1-b1a8-42aae82b7172", + "metadata": {}, + "source": [ + "# How to integrate LangGraph with AutoGen, CrewAI, and other frameworks\n", + "\n", + "LangGraph is a framework for building agentic and multi-agent applications. This includes integrating with other agent frameworks.\n", + "\n", + "This guides shows how to integrate LangGraph with other frameworks. The framework we show off integrating with is AutoGen, but this can easily be done with other frameworks.\n", + "\n", + "At a high level, the way this works is by wrapping the other agent inside a LangGraph node. LangGraph nodes can be anything - arbitrary code. This makes it easy to define an AutoGen (or CrewAI, or LlamaIndex, or other framework) agent and then reference it inside your graph. This allows you to create multi-agent systems where some of the sub-agents are actually defined in other frameworks." + ] + }, + { + "cell_type": "markdown", + "id": "b189ceb2-132b-4c7b-81b4-c7b8b062f833", + "metadata": {}, + "source": [ + "## Setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62417d3a-94f9-4a52-9962-12639d714966", + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install autogen bs4 langgraph langchain-openai langchain-community" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d46da41d-0a71-4654-aec8-9e6ad8765236", + "metadata": {}, + "outputs": [], + "source": [ + "# import os\n", + "# import getpass\n", + "\n", + "# os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()\n", + "# os.environ[\"TAVILY_API_KEY\"] = getpass.getpass()" + ] + }, + { + "cell_type": "markdown", + "id": "1926bbc3-6b06-41e0-9604-860a2bbf8fa3", + "metadata": {}, + "source": [ + "## Define AutoGen agent\n", + "\n", + "Here we define our AutoGen agent. From https://github.com/microsoft/autogen/blob/0.2/notebook/agentchat_web_info.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "524de117-ff09-4b26-bfe8-a9f85a46ffd5", + "metadata": {}, + "outputs": [], + "source": [ + "import autogen\n", + "import os\n", + "\n", + "config_list = [{\"model\": \"gpt-4o\", \"api_key\": os.environ[\"OPENAI_API_KEY\"]}]\n", + "\n", + "llm_config = {\n", + " \"timeout\": 600,\n", + " \"cache_seed\": 42,\n", + " \"config_list\": config_list,\n", + " \"temperature\": 0,\n", + "}\n", + "\n", + "autogen_agent = autogen.AssistantAgent(\n", + " name=\"assistant\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "user_proxy = autogen.UserProxyAgent(\n", + " name=\"user_proxy\",\n", + " human_input_mode=\"NEVER\",\n", + " max_consecutive_auto_reply=10,\n", + " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", + " code_execution_config={\n", + " \"work_dir\": \"web\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", + " llm_config=llm_config,\n", + " system_message=\"Reply TERMINATE if the task has been solved at full satisfaction. Otherwise, reply CONTINUE, or the reason why the task is not solved yet.\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "8aa858e2-4acb-4f75-be20-b9ccbbcb5073", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "d6bc7b69-4a36-44dc-a501-7e17122cc385", + "metadata": {}, + "source": [ + "## Define LangGraph agent\n", + "\n", + "We now define our LangGraph agent. We will create a simple ReAct-style agent with a web search tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a0fcdaac-8fbe-4589-8e61-8092165356cd", + "metadata": {}, + "outputs": [], + "source": [ + "from langgraph.graph import StateGraph, START, MessagesState\n", + "from langgraph.prebuilt import ToolNode, create_react_agent\n", + "from langchain_community.tools.tavily_search import TavilySearchResults\n", + "from langchain_openai import ChatOpenAI\n", + "from langchain_core.messages import HumanMessage, AIMessage\n", + "\n", + "model = ChatOpenAI(model=\"gpt-4o\")\n", + "tools = [TavilySearchResults(max_results=1)]\n", + "web_search_agent = create_react_agent(\n", + " model, tools, state_modifier=\"You are an agent specializing in web search\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "dcc478f5-4a35-43f8-bf59-9cb71289cd00", + "metadata": {}, + "source": [ + "## Create the multi-agent graph\n", + "\n", + "We will now create our multi-agent system combining the AutoGen agent with the LangGraph agent. We can do this by creating a graph that routes user query to the appropriate agent and executes the agent" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d129e4e1-3766-429a-b806-cde3d8bc0469", + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Literal, TypedDict\n", + "\n", + "\n", + "class Route(TypedDict):\n", + " \"\"\"Decide where to go next\"\"\"\n", + "\n", + " goto: Literal[\"web_search_assistant\", \"coding_assistant\"]\n", + "\n", + "\n", + "def route(state: MessagesState) -> Literal[\"web_search_assistant\", \"coding_assistant\"]:\n", + " messages = [\n", + " {\n", + " \"role\": \"system\",\n", + " \"content\": \"Based on the conversation so far, decide who to call next: web search assistant or coding assistant.\",\n", + " }\n", + " ] + state[\"messages\"]\n", + " response = model.with_structured_output(Route).invoke(messages)\n", + " return response[\"goto\"]\n", + "\n", + "\n", + "def call_autogen_agent(state: MessagesState):\n", + " last_message = state[\"messages\"][-1]\n", + " response = user_proxy.initiate_chat(autogen_agent, message=last_message.content)\n", + " # get the final response from the agent\n", + " content = response.chat_history[-1][\"content\"]\n", + " return {\"messages\": AIMessage(content=content)}\n", + "\n", + "\n", + "builder = StateGraph(MessagesState)\n", + "builder.add_conditional_edges(START, route)\n", + "builder.add_node(\"coding_assistant\", call_autogen_agent)\n", + "builder.add_node(\"web_search_assistant\", web_search_agent)\n", + "graph = builder.compile()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "c761fc05-e8b6-4905-a793-eb7522d20060", + "metadata": {}, + "outputs": [ + { + "data": { + "image/jpeg": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display, Image\n", + "\n", + "display(Image(graph.get_graph().draw_mermaid_png()))" + ] + }, + { + "cell_type": "markdown", + "id": "23d629c3-1d6b-40af-adf6-915e15657566", + "metadata": {}, + "source": [ + "## Run the graph\n", + "\n", + "We can now run the graph. We can see in the examples below how we first route to the appropriate agent, then respond with the subagent." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "b528ddb9-ec12-433c-a174-33d94dc49d80", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33muser_proxy\u001b[0m (to assistant):\n", + "\n", + "Find numbers between 10 and 30 in fibonacci sequence\n", + "\n", + "--------------------------------------------------------------------------------\n", + "\u001b[33massistant\u001b[0m (to user_proxy):\n", + "\n", + "To find numbers between 10 and 30 in the Fibonacci sequence, we can generate the Fibonacci sequence and check which numbers fall within this range. Here's a plan:\n", + "\n", + "1. Generate Fibonacci numbers starting from 0.\n", + "2. Continue generating until the numbers exceed 30.\n", + "3. Collect and print the numbers that are between 10 and 30.\n", + "\n", + "Let's implement this in Python:\n", + "\n", + "```python\n", + "# filename: fibonacci_range.py\n", + "\n", + "def fibonacci_sequence():\n", + " a, b = 0, 1\n", + " while a <= 30:\n", + " if 10 <= a <= 30:\n", + " print(a)\n", + " a, b = b, a + b\n", + "\n", + "fibonacci_sequence()\n", + "```\n", + "\n", + "Save this code in a file named `fibonacci_range.py` and execute it. It will print the Fibonacci numbers between 10 and 30. TERMINATE\n", + "\n", + "--------------------------------------------------------------------------------\n", + "{'coding_assistant': {'messages': AIMessage(content=\"To find numbers between 10 and 30 in the Fibonacci sequence, we can generate the Fibonacci sequence and check which numbers fall within this range. Here's a plan:\\n\\n1. Generate Fibonacci numbers starting from 0.\\n2. Continue generating until the numbers exceed 30.\\n3. Collect and print the numbers that are between 10 and 30.\\n\\nLet's implement this in Python:\\n\\n```python\\n# filename: fibonacci_range.py\\n\\ndef fibonacci_sequence():\\n a, b = 0, 1\\n while a <= 30:\\n if 10 <= a <= 30:\\n print(a)\\n a, b = b, a + b\\n\\nfibonacci_sequence()\\n```\\n\\nSave this code in a file named `fibonacci_range.py` and execute it. It will print the Fibonacci numbers between 10 and 30. TERMINATE\", additional_kwargs={}, response_metadata={}, id='e95a8aa1-5aa8-4ff2-ba74-2b2993ea0a5a')}}\n" + ] + } + ], + "source": [ + "for chunk in graph.stream(\n", + " {\n", + " \"messages\": [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": \"Find numbers between 10 and 30 in fibonacci sequence\",\n", + " }\n", + " ]\n", + " }\n", + "):\n", + " print(chunk)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b120f9ba-f640-482b-a457-1893d6db5543", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(('web_search_assistant:d08ae326-b6b2-1749-e8ea-4d308f22d819',), {'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_wZ5w5uO733Cc4CvWbc4Axq5F', 'function': {'arguments': '{\"query\":\"current weather in New York City\"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 23, 'prompt_tokens': 96, 'total_tokens': 119, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_45cf54deae', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-0658af11-b90b-407c-a6a5-6a3b4a9f61e0-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in New York City'}, 'id': 'call_wZ5w5uO733Cc4CvWbc4Axq5F', 'type': 'tool_call'}], usage_metadata={'input_tokens': 96, 'output_tokens': 23, 'total_tokens': 119, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}})\n", + "(('web_search_assistant:d08ae326-b6b2-1749-e8ea-4d308f22d819',), {'tools': {'messages': [ToolMessage(content='[{\"url\": \"https://www.weatherapi.com/\", \"content\": \"{\\'location\\': {\\'name\\': \\'New York\\', \\'region\\': \\'New York\\', \\'country\\': \\'United States of America\\', \\'lat\\': 40.714, \\'lon\\': -74.006, \\'tz_id\\': \\'America/New_York\\', \\'localtime_epoch\\': 1732021037, \\'localtime\\': \\'2024-11-19 07:57\\'}, \\'current\\': {\\'last_updated_epoch\\': 1732020300, \\'last_updated\\': \\'2024-11-19 07:45\\', \\'temp_c\\': 8.3, \\'temp_f\\': 46.9, \\'is_day\\': 1, \\'condition\\': {\\'text\\': \\'Sunny\\', \\'icon\\': \\'//cdn.weatherapi.com/weather/64x64/day/113.png\\', \\'code\\': 1000}, \\'wind_mph\\': 7.2, \\'wind_kph\\': 11.5, \\'wind_degree\\': 332, \\'wind_dir\\': \\'NNW\\', \\'pressure_mb\\': 1016.0, \\'pressure_in\\': 29.99, \\'precip_mm\\': 0.0, \\'precip_in\\': 0.0, \\'humidity\\': 60, \\'cloud\\': 0, \\'feelslike_c\\': 6.3, \\'feelslike_f\\': 43.4, \\'windchill_c\\': 4.3, \\'windchill_f\\': 39.8, \\'heatindex_c\\': 7.0, \\'heatindex_f\\': 44.5, \\'dewpoint_c\\': 2.7, \\'dewpoint_f\\': 36.8, \\'vis_km\\': 16.0, \\'vis_miles\\': 9.0, \\'uv\\': 0.0, \\'gust_mph\\': 10.0, \\'gust_kph\\': 16.2}}\"}]', name='tavily_search_results_json', id='e955ebe9-631f-4dd1-b0a4-ee6a3caeba9f', tool_call_id='call_wZ5w5uO733Cc4CvWbc4Axq5F', artifact={'query': 'current weather in New York City', 'follow_up_questions': None, 'answer': None, 'images': [], 'results': [{'title': 'Weather in New York City', 'url': 'https://www.weatherapi.com/', 'content': \"{'location': {'name': 'New York', 'region': 'New York', 'country': 'United States of America', 'lat': 40.714, 'lon': -74.006, 'tz_id': 'America/New_York', 'localtime_epoch': 1732021037, 'localtime': '2024-11-19 07:57'}, 'current': {'last_updated_epoch': 1732020300, 'last_updated': '2024-11-19 07:45', 'temp_c': 8.3, 'temp_f': 46.9, 'is_day': 1, 'condition': {'text': 'Sunny', 'icon': '//cdn.weatherapi.com/weather/64x64/day/113.png', 'code': 1000}, 'wind_mph': 7.2, 'wind_kph': 11.5, 'wind_degree': 332, 'wind_dir': 'NNW', 'pressure_mb': 1016.0, 'pressure_in': 29.99, 'precip_mm': 0.0, 'precip_in': 0.0, 'humidity': 60, 'cloud': 0, 'feelslike_c': 6.3, 'feelslike_f': 43.4, 'windchill_c': 4.3, 'windchill_f': 39.8, 'heatindex_c': 7.0, 'heatindex_f': 44.5, 'dewpoint_c': 2.7, 'dewpoint_f': 36.8, 'vis_km': 16.0, 'vis_miles': 9.0, 'uv': 0.0, 'gust_mph': 10.0, 'gust_kph': 16.2}}\", 'score': 0.9997275, 'raw_content': None}], 'response_time': 3.24})]}})\n", + "(('web_search_assistant:d08ae326-b6b2-1749-e8ea-4d308f22d819',), {'agent': {'messages': [AIMessage(content='The current weather in New York City is sunny with a temperature of 8.3°C (46.9°F). The wind is coming from the north-northwest at 7.2 mph (11.5 kph), and the humidity level is 60%. The weather feels slightly cooler at 6.3°C (43.4°F) due to the wind chill.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 79, 'prompt_tokens': 535, 'total_tokens': 614, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_159d8341cc', 'finish_reason': 'stop', 'logprobs': None}, id='run-43d275f1-aacb-44f4-bdd0-8233c3765699-0', usage_metadata={'input_tokens': 535, 'output_tokens': 79, 'total_tokens': 614, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}})\n", + "((), {'web_search_assistant': {'messages': [HumanMessage(content=\"what's the weather in nyc?\", additional_kwargs={}, response_metadata={}, id='756466d3-18ce-4b8e-b4fc-ee59932ce9f4'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_wZ5w5uO733Cc4CvWbc4Axq5F', 'function': {'arguments': '{\"query\":\"current weather in New York City\"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 23, 'prompt_tokens': 96, 'total_tokens': 119, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_45cf54deae', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-0658af11-b90b-407c-a6a5-6a3b4a9f61e0-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in New York City'}, 'id': 'call_wZ5w5uO733Cc4CvWbc4Axq5F', 'type': 'tool_call'}], usage_metadata={'input_tokens': 96, 'output_tokens': 23, 'total_tokens': 119, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}), ToolMessage(content='[{\"url\": \"https://www.weatherapi.com/\", \"content\": \"{\\'location\\': {\\'name\\': \\'New York\\', \\'region\\': \\'New York\\', \\'country\\': \\'United States of America\\', \\'lat\\': 40.714, \\'lon\\': -74.006, \\'tz_id\\': \\'America/New_York\\', \\'localtime_epoch\\': 1732021037, \\'localtime\\': \\'2024-11-19 07:57\\'}, \\'current\\': {\\'last_updated_epoch\\': 1732020300, \\'last_updated\\': \\'2024-11-19 07:45\\', \\'temp_c\\': 8.3, \\'temp_f\\': 46.9, \\'is_day\\': 1, \\'condition\\': {\\'text\\': \\'Sunny\\', \\'icon\\': \\'//cdn.weatherapi.com/weather/64x64/day/113.png\\', \\'code\\': 1000}, \\'wind_mph\\': 7.2, \\'wind_kph\\': 11.5, \\'wind_degree\\': 332, \\'wind_dir\\': \\'NNW\\', \\'pressure_mb\\': 1016.0, \\'pressure_in\\': 29.99, \\'precip_mm\\': 0.0, \\'precip_in\\': 0.0, \\'humidity\\': 60, \\'cloud\\': 0, \\'feelslike_c\\': 6.3, \\'feelslike_f\\': 43.4, \\'windchill_c\\': 4.3, \\'windchill_f\\': 39.8, \\'heatindex_c\\': 7.0, \\'heatindex_f\\': 44.5, \\'dewpoint_c\\': 2.7, \\'dewpoint_f\\': 36.8, \\'vis_km\\': 16.0, \\'vis_miles\\': 9.0, \\'uv\\': 0.0, \\'gust_mph\\': 10.0, \\'gust_kph\\': 16.2}}\"}]', name='tavily_search_results_json', id='e955ebe9-631f-4dd1-b0a4-ee6a3caeba9f', tool_call_id='call_wZ5w5uO733Cc4CvWbc4Axq5F', artifact={'query': 'current weather in New York City', 'follow_up_questions': None, 'answer': None, 'images': [], 'results': [{'title': 'Weather in New York City', 'url': 'https://www.weatherapi.com/', 'content': \"{'location': {'name': 'New York', 'region': 'New York', 'country': 'United States of America', 'lat': 40.714, 'lon': -74.006, 'tz_id': 'America/New_York', 'localtime_epoch': 1732021037, 'localtime': '2024-11-19 07:57'}, 'current': {'last_updated_epoch': 1732020300, 'last_updated': '2024-11-19 07:45', 'temp_c': 8.3, 'temp_f': 46.9, 'is_day': 1, 'condition': {'text': 'Sunny', 'icon': '//cdn.weatherapi.com/weather/64x64/day/113.png', 'code': 1000}, 'wind_mph': 7.2, 'wind_kph': 11.5, 'wind_degree': 332, 'wind_dir': 'NNW', 'pressure_mb': 1016.0, 'pressure_in': 29.99, 'precip_mm': 0.0, 'precip_in': 0.0, 'humidity': 60, 'cloud': 0, 'feelslike_c': 6.3, 'feelslike_f': 43.4, 'windchill_c': 4.3, 'windchill_f': 39.8, 'heatindex_c': 7.0, 'heatindex_f': 44.5, 'dewpoint_c': 2.7, 'dewpoint_f': 36.8, 'vis_km': 16.0, 'vis_miles': 9.0, 'uv': 0.0, 'gust_mph': 10.0, 'gust_kph': 16.2}}\", 'score': 0.9997275, 'raw_content': None}], 'response_time': 3.24}), AIMessage(content='The current weather in New York City is sunny with a temperature of 8.3°C (46.9°F). The wind is coming from the north-northwest at 7.2 mph (11.5 kph), and the humidity level is 60%. The weather feels slightly cooler at 6.3°C (43.4°F) due to the wind chill.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 79, 'prompt_tokens': 535, 'total_tokens': 614, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_159d8341cc', 'finish_reason': 'stop', 'logprobs': None}, id='run-43d275f1-aacb-44f4-bdd0-8233c3765699-0', usage_metadata={'input_tokens': 535, 'output_tokens': 79, 'total_tokens': 614, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}})\n" + ] + } + ], + "source": [ + "for chunk in graph.stream(\n", + " {\"messages\": [{\"role\": \"user\", \"content\": \"what's the weather in nyc?\"}]},\n", + " subgraphs=True,\n", + "):\n", + " print(chunk)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ab2a7e63-a842-4e58-9c6a-e2203edec7b0", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/docs/how-tos/autogen-langgraph-platform.ipynb b/docs/docs/how-tos/autogen-langgraph-platform.ipynb new file mode 100644 index 000000000..0d8cc4b19 --- /dev/null +++ b/docs/docs/how-tos/autogen-langgraph-platform.ipynb @@ -0,0 +1,173 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "8381b6e0-29a6-48c5-b451-5d2549351249", + "metadata": {}, + "source": [ + "# How to use LangGraph Platform to deploy CrewAI, AutoGen, and other frameworks\n", + "\n", + "[LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) provides infrastructure for deploying agents. This integrates seamlessly with LangGraph, but can also work with other frameworks. The way to make this work is to wrap the agent in a single LangGraph node, and have that be the entire graph.\n", + "\n", + "Doing so will allow you to deploy to LangGraph Platform, and allows you to get a lot of the [benefits](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/). You get horizontally scalable infrastructure, a task queue to handle bursty operations, a persistence layer to power short term memory, and long term memory support.\n", + "\n", + "In this guide we show how to do this with an AutoGen agent, but this method should work for agents defined in other frameworks like CrewAI, LlamaIndex, and others as well." + ] + }, + { + "cell_type": "markdown", + "id": "1113cb16-b538-448c-924c-85731ce96ebd", + "metadata": {}, + "source": [ + "## Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "f05993fa-9d03-4f45-bc13-0a8d87260d86", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# %pip install autogen langgraph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4e0ca12-1714-4776-a30a-9527e519799b", + "metadata": {}, + "outputs": [], + "source": [ + "# import os\n", + "# import getpass\n", + "\n", + "# os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()" + ] + }, + { + "cell_type": "markdown", + "id": "1926bbc3-6b06-41e0-9604-860a2bbf8fa3", + "metadata": {}, + "source": [ + "## Define autogen agent\n", + "\n", + "Here we define our AutoGen agent. From https://github.com/microsoft/autogen/blob/0.2/notebook/agentchat_web_info.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d4a14dc7-d565-4207-8788-525f85b9fb27", + "metadata": {}, + "outputs": [], + "source": [ + "import autogen\n", + "import os\n", + "\n", + "config_list = [{\"model\": \"gpt-4o\", \"api_key\": os.environ[\"OPENAI_API_KEY\"]}]\n", + "\n", + "llm_config = {\n", + " \"timeout\": 600,\n", + " \"cache_seed\": 42,\n", + " \"config_list\": config_list,\n", + " \"temperature\": 0,\n", + "}\n", + "\n", + "autogen_agent = autogen.AssistantAgent(\n", + " name=\"assistant\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "user_proxy = autogen.UserProxyAgent(\n", + " name=\"user_proxy\",\n", + " human_input_mode=\"NEVER\",\n", + " max_consecutive_auto_reply=10,\n", + " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", + " code_execution_config={\n", + " \"work_dir\": \"web\",\n", + " \"use_docker\": False,\n", + " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", + " llm_config=llm_config,\n", + " system_message=\"Reply TERMINATE if the task has been solved at full satisfaction. Otherwise, reply CONTINUE, or the reason why the task is not solved yet.\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "b1170836-f23e-4e4c-ab83-ce791cd7fbd2", + "metadata": {}, + "source": [ + "## Wrap in LangGraph\n", + "\n", + "We now wrap the AutoGen agent in a single LangGraph node, and make that the entire graph.\n", + "The main thing this involves is defining an Input and Output schema for the node, which you would need to do if deploying this manually, so it's no extra work" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7b417c16-ff4e-4d5c-a9a9-0aaeeef6ede5", + "metadata": {}, + "outputs": [], + "source": [ + "from langgraph.graph import StateGraph, MessagesState\n", + "\n", + "\n", + "def call_autogen_agent(state: MessagesState):\n", + " last_message = state[\"messages\"][-1]\n", + " response = user_proxy.initiate_chat(autogen_agent, message=last_message.content)\n", + " # get the final response from the agent\n", + " content = response.chat_history[-1][\"content\"]\n", + " return {\"messages\": {\"role\": \"assistant\", \"content\": content}}\n", + "\n", + "\n", + "graph = StateGraph(MessagesState)\n", + "graph.add_node(call_autogen_agent)\n", + "graph.set_entry_point(\"call_autogen_agent\")\n", + "graph = graph.compile()" + ] + }, + { + "cell_type": "markdown", + "id": "f6a18377-ac29-478f-a76a-b213f1a3c85d", + "metadata": {}, + "source": [ + "## Deploy with LangGraph Platform\n", + "\n", + "You can now deploy this as you normally would with LangGraph Platform. See [these instructions](https://langchain-ai.github.io/langgraph/concepts/deployment_options/) for more details." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b9c3ecb-0f36-4cfb-a10f-8a2e0ef6c730", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/docs/how-tos/configuration.ipynb b/docs/docs/how-tos/configuration.ipynb index 7ea271681..589131b95 100644 --- a/docs/docs/how-tos/configuration.ipynb +++ b/docs/docs/how-tos/configuration.ipynb @@ -345,7 +345,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.11.1" } }, "nbformat": 4, diff --git a/docs/docs/how-tos/index.md b/docs/docs/how-tos/index.md index 92e7b526c..a224e0f31 100644 --- a/docs/docs/how-tos/index.md +++ b/docs/docs/how-tos/index.md @@ -103,6 +103,7 @@ These how-to guides show common patterns for tool calling with LangGraph: - [How to force function calling agent to structure output](react-agent-structured-output.ipynb) - [How to pass custom LangSmith run ID for graph runs](run-id-langsmith.ipynb) - [How to return state before hitting recursion limit](return-when-recursion-limit-hits.ipynb) +- [How to integrate LangGraph with AutoGen, CrewAI, and other frameworks](autogen-integration.ipynb) ### Prebuilt ReAct Agent @@ -141,6 +142,7 @@ Learn how to set up your app for deployment to LangGraph Platform: - [How to customize Dockerfile](../cloud/deployment/custom_docker.md) - [How to test locally](../cloud/deployment/test_locally.md) - [How to rebuild graph at runtime](../cloud/deployment/graph_rebuild.md) +- [How to use LangGraph Platform to deploy CrewAI, AutoGen, and other frameworks](autogen-langgraph-platform.ipynb) ### Deployment diff --git a/poetry.lock b/poetry.lock index 64529d4aa..7d0162abb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -390,6 +390,59 @@ docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphi tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +[[package]] +name = "autogen" +version = "0.3.2" +description = "A programming framework for agentic AI" +optional = false +python-versions = "<3.13,>=3.8" +files = [ + {file = "autogen-0.3.2-py3-none-any.whl", hash = "sha256:e37a9df0ad84cde3429ec63298b8e9eb4e6306a28eec2627171e14b9a61ea64d"}, + {file = "autogen-0.3.2.tar.gz", hash = "sha256:9f8a1170ac2e5a1fc9efc3cfa6e23261dd014db97b17c8c416f97ee14951bc7b"}, +] + +[package.dependencies] +diskcache = "*" +docker = "*" +flaml = "*" +numpy = ">=1.17.0,<2" +openai = ">=1.3" +packaging = "*" +pydantic = ">=1.10,<2.6.0 || >2.6.0,<3" +python-dotenv = "*" +termcolor = "*" +tiktoken = "*" + +[package.extras] +anthropic = ["anthropic (>=0.23.1)"] +autobuild = ["chromadb", "huggingface-hub", "pysqlite3", "sentence-transformers"] +bedrock = ["boto3 (>=1.34.149)"] +blendsearch = ["flaml[blendsearch]"] +cerebras = ["cerebras-cloud-sdk (>=1.0.0)"] +cohere = ["cohere (>=5.5.8)"] +cosmosdb = ["azure-cosmos (>=4.2.0)"] +gemini = ["google-auth", "google-cloud-aiplatform", "google-generativeai (>=0.5,<1)", "pillow", "pydantic"] +graph = ["matplotlib", "networkx"] +graph-rag-falkor-db = ["graphrag-sdk"] +groq = ["groq (>=0.9.0)"] +jupyter-executor = ["ipykernel (>=6.29.0)", "jupyter-client (>=8.6.0)", "jupyter-kernel-gateway", "requests", "websocket-client"] +lmm = ["pillow", "replicate"] +long-context = ["llmlingua (<0.3)"] +mathchat = ["pydantic (==1.10.9)", "sympy", "wolframalpha"] +mistral = ["mistralai (>=1.0.1)"] +ollama = ["fix-busted-json (>=0.0.18)", "ollama (>=0.3.3)"] +redis = ["redis"] +retrievechat = ["beautifulsoup4", "chromadb (==0.5.3)", "ipython", "markdownify", "protobuf (==4.25.3)", "pypdf", "sentence-transformers"] +retrievechat-mongodb = ["beautifulsoup4", "chromadb (==0.5.3)", "ipython", "markdownify", "protobuf (==4.25.3)", "pymongo (>=4.0.0)", "pypdf", "sentence-transformers"] +retrievechat-pgvector = ["beautifulsoup4", "chromadb (==0.5.3)", "ipython", "markdownify", "pgvector (>=0.2.5)", "protobuf (==4.25.3)", "psycopg (>=3.1.18)", "pypdf", "sentence-transformers"] +retrievechat-qdrant = ["beautifulsoup4", "chromadb (==0.5.3)", "fastembed (>=0.3.1)", "ipython", "markdownify", "protobuf (==4.25.3)", "pypdf", "qdrant-client", "sentence-transformers"] +teachable = ["chromadb"] +test = ["ipykernel", "nbconvert", "nbformat", "pandas", "pre-commit", "pytest (>=6.1.1,<8)", "pytest-asyncio", "pytest-cov (>=5)"] +together = ["together (>=1.2)"] +types = ["ipykernel (>=6.29.0)", "jupyter-client (>=8.6.0)", "jupyter-kernel-gateway", "mypy (==1.9.0)", "pytest (>=6.1.1,<8)", "requests", "websocket-client"] +websockets = ["websockets (>=12.0,<13)"] +websurfer = ["beautifulsoup4", "markdownify", "pathvalidate", "pdfminer.six"] + [[package]] name = "babel" version = "2.16.0" @@ -1135,6 +1188,17 @@ wrapt = ">=1.10,<2" [package.extras] dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] +[[package]] +name = "diskcache" +version = "5.6.3" +description = "Disk Cache -- Disk and file backed persistent cache." +optional = false +python-versions = ">=3" +files = [ + {file = "diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19"}, + {file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"}, +] + [[package]] name = "distro" version = "1.9.0" @@ -1166,6 +1230,28 @@ idna = ["idna (>=3.6)"] trio = ["trio (>=0.23)"] wmi = ["wmi (>=1.5.1)"] +[[package]] +name = "docker" +version = "7.1.0" +description = "A Python library for the Docker Engine API." +optional = false +python-versions = ">=3.8" +files = [ + {file = "docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0"}, + {file = "docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c"}, +] + +[package.dependencies] +pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""} +requests = ">=2.26.0" +urllib3 = ">=1.26.0" + +[package.extras] +dev = ["coverage (==7.2.7)", "pytest (==7.4.2)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.1.0)", "ruff (==0.1.8)"] +docs = ["myst-parser (==0.18.0)", "sphinx (==5.1.1)"] +ssh = ["paramiko (>=2.4.3)"] +websockets = ["websocket-client (>=1.3.0)"] + [[package]] name = "durationpy" version = "0.7" @@ -1271,6 +1357,43 @@ httpx-sse = "*" Pillow = "*" pydantic = "*" +[[package]] +name = "flaml" +version = "2.3.2" +description = "A fast library for automated machine learning and tuning" +optional = false +python-versions = ">=3.8" +files = [ + {file = "FLAML-2.3.2-py3-none-any.whl", hash = "sha256:1ee6e8e76bf1d741b4da41e2a2a8c0638b36d90b0f60aac323b5568f54dcb9e7"}, + {file = "flaml-2.3.2.tar.gz", hash = "sha256:4a1ec289ddaec36850cfc66f6fb335b8521df49ea31f6adb54ea63a5cebb6865"}, +] + +[package.dependencies] +NumPy = ">=1.17" + +[package.extras] +autogen = ["diskcache", "openai (==0.27.8)", "termcolor"] +automl = ["lightgbm (>=2.3.1)", "pandas (>=1.1.4)", "scikit-learn (>=1.0.0)", "scipy (>=1.4.1)", "xgboost (>=0.90,<3.0.0)"] +autozero = ["packaging", "pandas", "scikit-learn"] +azureml = ["azureml-mlflow"] +benchmark = ["catboost (>=0.26)", "pandas (==1.1.4)", "psutil (==5.8.0)", "xgboost (==1.3.3)"] +blendsearch = ["optuna (>=2.8.0,<=3.6.1)", "packaging"] +catboost = ["catboost (>=0.26,<1.2)", "catboost (>=0.26,<=1.2.5)"] +forecast = ["hcrystalball (==0.1.10)", "holidays (<0.14)", "prophet (>=1.0.1)", "pytorch-forecasting (>=0.9.0)", "pytorch-lightning (==1.9.0)", "statsmodels (>=0.12.2)", "tensorboardX (==2.6)"] +hf = ["datasets", "nltk (<=3.8.1)", "rouge-score", "seqeval", "transformers[torch] (==4.26)"] +mathchat = ["diskcache", "openai (==0.27.8)", "pydantic (==1.10.9)", "sympy", "termcolor", "wolframalpha"] +nlp = ["datasets", "nltk (<=3.8.1)", "rouge-score", "seqeval", "transformers[torch] (==4.26)"] +nni = ["nni"] +notebook = ["jupyter"] +openai = ["diskcache", "openai (==0.27.8)"] +ray = ["ray[tune] (>=1.13,<2.0)"] +retrievechat = ["chromadb", "diskcache", "openai (==0.27.8)", "sentence-transformers", "termcolor", "tiktoken"] +spark = ["joblib (<=1.3.2)", "joblibspark (>=0.5.0)", "pyspark (>=3.2.0)"] +synapse = ["joblibspark (>=0.5.0)", "optuna (>=2.8.0,<=3.6.1)", "pyspark (>=3.2.0)"] +test = ["catboost (>=0.26)", "catboost (>=0.26,<1.2)", "coverage (>=5.3)", "dataclasses", "datasets", "dill", "hcrystalball (==0.1.10)", "ipykernel", "joblib (<=1.3.2)", "joblibspark (>=0.5.0)", "jupyter", "lightgbm (>=2.3.1)", "mlflow (==2.15.1)", "nbconvert", "nbformat", "nltk (<=3.8.1)", "openml", "optuna (>=2.8.0,<=3.6.1)", "packaging", "pandas (>=1.1.4)", "pandas (>=1.1.4,<2.0.0)", "pre-commit", "psutil (==5.8.0)", "pydantic (==1.10.9)", "pytest (>=6.1.1)", "pytorch-forecasting (>=0.9.0,<=0.10.1)", "pytorch-lightning (<1.9.1)", "requests (<2.29.0)", "rgf-python", "rouge-score", "scikit-learn (>=1.0.0)", "scipy (>=1.4.1)", "seqeval", "statsmodels (>=0.12.2)", "sympy", "tensorboardX (==2.6)", "thop", "torch", "torchvision", "transformers[torch] (==4.26)", "wolframalpha", "xgboost (>=0.90,<2.0.0)"] +ts-forecast = ["hcrystalball (==0.1.10)", "holidays (<0.14)", "prophet (>=1.0.1)", "statsmodels (>=0.12.2)"] +vw = ["scikit-learn", "vowpalwabbit (>=8.10.0,<9.0.0)"] + [[package]] name = "flatbuffers" version = "24.3.25" @@ -2912,7 +3035,7 @@ langchain-core = ">=0.3.0,<0.4.0" [[package]] name = "langgraph" -version = "0.2.34" +version = "0.2.52" description = "Building stateful, multi-actor applications with LLMs" optional = false python-versions = ">=3.9.0,<4.0" @@ -2920,8 +3043,9 @@ files = [] develop = true [package.dependencies] -langchain-core = ">=0.2.39,<0.4" -langgraph-checkpoint = "^2.0.0" +langchain-core = ">=0.2.43,<0.4.0,!=0.3.0,!=0.3.1,!=0.3.2,!=0.3.3,!=0.3.4,!=0.3.5,!=0.3.6,!=0.3.7,!=0.3.8,!=0.3.9,!=0.3.10,!=0.3.11,!=0.3.12,!=0.3.13,!=0.3.14" +langgraph-checkpoint = "^2.0.4" +langgraph-sdk = "^0.1.32" [package.source] type = "directory" @@ -2929,7 +3053,7 @@ url = "libs/langgraph" [[package]] name = "langgraph-checkpoint" -version = "2.0.1" +version = "2.0.5" description = "Library with base interfaces for LangGraph checkpoint savers." optional = false python-versions = "^3.9.0,<4.0" @@ -2946,7 +3070,7 @@ url = "libs/checkpoint" [[package]] name = "langgraph-checkpoint-postgres" -version = "2.0.1" +version = "2.0.3" description = "Library with a Postgres implementation of LangGraph checkpoint saver." optional = false python-versions = "^3.9.0,<4.0" @@ -2954,7 +3078,7 @@ files = [] develop = true [package.dependencies] -langgraph-checkpoint = "^2.0.0" +langgraph-checkpoint = "^2.0.2" orjson = ">=3.10.1" psycopg = "^3.0.0" psycopg-pool = "^3.0.0" @@ -2965,7 +3089,7 @@ url = "libs/checkpoint-postgres" [[package]] name = "langgraph-checkpoint-sqlite" -version = "2.0.0" +version = "2.0.1" description = "Library with a SQLite implementation of LangGraph checkpoint saver." optional = false python-versions = "^3.9.0" @@ -2974,7 +3098,7 @@ develop = true [package.dependencies] aiosqlite = "^0.20.0" -langgraph-checkpoint = "^2.0.0" +langgraph-checkpoint = "^2.0.2" [package.source] type = "directory" @@ -2982,7 +3106,7 @@ url = "libs/checkpoint-sqlite" [[package]] name = "langgraph-sdk" -version = "0.1.32" +version = "0.1.36" description = "SDK for interacting with LangGraph API" optional = false python-versions = "^3.9.0,<4.0" @@ -4974,6 +5098,7 @@ description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs optional = false python-versions = ">=3.8" files = [ + {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, ] @@ -4984,6 +5109,7 @@ description = "A collection of ASN.1-based protocols modules" optional = false python-versions = ">=3.8" files = [ + {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, ] @@ -6043,6 +6169,11 @@ files = [ {file = "scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f60021ec1574e56632be2a36b946f8143bf4e5e6af4a06d85281adc22938e0dd"}, {file = "scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:394397841449853c2290a32050382edaec3da89e35b3e03d6cc966aebc6a8ae6"}, {file = "scikit_learn-1.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:57cc1786cfd6bd118220a92ede80270132aa353647684efa385a74244a41e3b1"}, + {file = "scikit_learn-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9a702e2de732bbb20d3bad29ebd77fc05a6b427dc49964300340e4c9328b3f5"}, + {file = "scikit_learn-1.5.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:b0768ad641981f5d3a198430a1d31c3e044ed2e8a6f22166b4d546a5116d7908"}, + {file = "scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:178ddd0a5cb0044464fc1bfc4cca5b1833bfc7bb022d70b05db8530da4bb3dd3"}, + {file = "scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7284ade780084d94505632241bf78c44ab3b6f1e8ccab3d2af58e0e950f9c12"}, + {file = "scikit_learn-1.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:b7b0f9a0b1040830d38c39b91b3a44e1b643f4b36e36567b80b7c6bd2202a27f"}, {file = "scikit_learn-1.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:757c7d514ddb00ae249832fe87100d9c73c6ea91423802872d9e74970a0e40b9"}, {file = "scikit_learn-1.5.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:52788f48b5d8bca5c0736c175fa6bdaab2ef00a8f536cda698db61bd89c551c1"}, {file = "scikit_learn-1.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:643964678f4b5fbdc95cbf8aec638acc7aa70f5f79ee2cdad1eec3df4ba6ead8"}, @@ -6362,6 +6493,20 @@ files = [ doc = ["reno", "sphinx"] test = ["pytest", "tornado (>=4.5)", "typeguard"] +[[package]] +name = "termcolor" +version = "2.5.0" +description = "ANSI color formatting for output in terminal" +optional = false +python-versions = ">=3.9" +files = [ + {file = "termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8"}, + {file = "termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + [[package]] name = "terminado" version = "0.18.1" @@ -7331,4 +7476,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "738e69cf406b140217cc8c3c0f2ccb5c2027d4701bcf2a347ba4b107f700ab2a" +content-hash = "776ee42630769f08e3896338f18ec81830166695d32d2208dc31dedb22d3b22d" diff --git a/pyproject.toml b/pyproject.toml index dc50e167f..31fe17172 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ motor = "^3.5.1" grandalf = "^0.8" pyppeteer = "^2.0.0" networkx = "^3.3" +autogen = { version = "^0.3.0", python = "<3.13,>=3.8" } [tool.poetry.group.test] optional = true