ag2 0.10.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ag2-0.10.2.dist-info/METADATA +819 -0
- ag2-0.10.2.dist-info/RECORD +423 -0
- ag2-0.10.2.dist-info/WHEEL +4 -0
- ag2-0.10.2.dist-info/licenses/LICENSE +201 -0
- ag2-0.10.2.dist-info/licenses/NOTICE.md +19 -0
- autogen/__init__.py +88 -0
- autogen/_website/__init__.py +3 -0
- autogen/_website/generate_api_references.py +426 -0
- autogen/_website/generate_mkdocs.py +1216 -0
- autogen/_website/notebook_processor.py +475 -0
- autogen/_website/process_notebooks.py +656 -0
- autogen/_website/utils.py +413 -0
- autogen/a2a/__init__.py +36 -0
- autogen/a2a/agent_executor.py +86 -0
- autogen/a2a/client.py +357 -0
- autogen/a2a/errors.py +18 -0
- autogen/a2a/httpx_client_factory.py +79 -0
- autogen/a2a/server.py +221 -0
- autogen/a2a/utils.py +207 -0
- autogen/agentchat/__init__.py +47 -0
- autogen/agentchat/agent.py +180 -0
- autogen/agentchat/assistant_agent.py +86 -0
- autogen/agentchat/chat.py +325 -0
- autogen/agentchat/contrib/__init__.py +5 -0
- autogen/agentchat/contrib/agent_eval/README.md +7 -0
- autogen/agentchat/contrib/agent_eval/agent_eval.py +108 -0
- autogen/agentchat/contrib/agent_eval/criterion.py +43 -0
- autogen/agentchat/contrib/agent_eval/critic_agent.py +44 -0
- autogen/agentchat/contrib/agent_eval/quantifier_agent.py +39 -0
- autogen/agentchat/contrib/agent_eval/subcritic_agent.py +45 -0
- autogen/agentchat/contrib/agent_eval/task.py +42 -0
- autogen/agentchat/contrib/agent_optimizer.py +432 -0
- autogen/agentchat/contrib/capabilities/__init__.py +5 -0
- autogen/agentchat/contrib/capabilities/agent_capability.py +20 -0
- autogen/agentchat/contrib/capabilities/generate_images.py +301 -0
- autogen/agentchat/contrib/capabilities/teachability.py +393 -0
- autogen/agentchat/contrib/capabilities/text_compressors.py +66 -0
- autogen/agentchat/contrib/capabilities/tools_capability.py +22 -0
- autogen/agentchat/contrib/capabilities/transform_messages.py +93 -0
- autogen/agentchat/contrib/capabilities/transforms.py +578 -0
- autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
- autogen/agentchat/contrib/capabilities/vision_capability.py +215 -0
- autogen/agentchat/contrib/captainagent/__init__.py +9 -0
- autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
- autogen/agentchat/contrib/captainagent/captainagent.py +514 -0
- autogen/agentchat/contrib/captainagent/tool_retriever.py +334 -0
- autogen/agentchat/contrib/captainagent/tools/README.md +44 -0
- autogen/agentchat/contrib/captainagent/tools/__init__.py +5 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +40 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +30 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +27 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +53 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +53 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +38 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +34 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +60 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +61 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +47 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +33 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +35 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +18 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +31 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +16 -0
- autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +25 -0
- autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +23 -0
- autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +27 -0
- autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +34 -0
- autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +39 -0
- autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +23 -0
- autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +36 -0
- autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +15 -0
- autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +15 -0
- autogen/agentchat/contrib/captainagent/tools/requirements.txt +10 -0
- autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +34 -0
- autogen/agentchat/contrib/gpt_assistant_agent.py +526 -0
- autogen/agentchat/contrib/graph_rag/__init__.py +9 -0
- autogen/agentchat/contrib/graph_rag/document.py +29 -0
- autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +167 -0
- autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +103 -0
- autogen/agentchat/contrib/graph_rag/graph_query_engine.py +53 -0
- autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +63 -0
- autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +263 -0
- autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +83 -0
- autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +210 -0
- autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +93 -0
- autogen/agentchat/contrib/img_utils.py +397 -0
- autogen/agentchat/contrib/llamaindex_conversable_agent.py +117 -0
- autogen/agentchat/contrib/llava_agent.py +189 -0
- autogen/agentchat/contrib/math_user_proxy_agent.py +464 -0
- autogen/agentchat/contrib/multimodal_conversable_agent.py +125 -0
- autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +325 -0
- autogen/agentchat/contrib/rag/__init__.py +10 -0
- autogen/agentchat/contrib/rag/chromadb_query_engine.py +268 -0
- autogen/agentchat/contrib/rag/llamaindex_query_engine.py +195 -0
- autogen/agentchat/contrib/rag/mongodb_query_engine.py +319 -0
- autogen/agentchat/contrib/rag/query_engine.py +76 -0
- autogen/agentchat/contrib/retrieve_assistant_agent.py +59 -0
- autogen/agentchat/contrib/retrieve_user_proxy_agent.py +704 -0
- autogen/agentchat/contrib/society_of_mind_agent.py +200 -0
- autogen/agentchat/contrib/swarm_agent.py +1404 -0
- autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
- autogen/agentchat/contrib/vectordb/__init__.py +5 -0
- autogen/agentchat/contrib/vectordb/base.py +224 -0
- autogen/agentchat/contrib/vectordb/chromadb.py +316 -0
- autogen/agentchat/contrib/vectordb/couchbase.py +405 -0
- autogen/agentchat/contrib/vectordb/mongodb.py +551 -0
- autogen/agentchat/contrib/vectordb/pgvectordb.py +927 -0
- autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
- autogen/agentchat/contrib/vectordb/utils.py +126 -0
- autogen/agentchat/contrib/web_surfer.py +304 -0
- autogen/agentchat/conversable_agent.py +4307 -0
- autogen/agentchat/group/__init__.py +67 -0
- autogen/agentchat/group/available_condition.py +91 -0
- autogen/agentchat/group/context_condition.py +77 -0
- autogen/agentchat/group/context_expression.py +238 -0
- autogen/agentchat/group/context_str.py +39 -0
- autogen/agentchat/group/context_variables.py +182 -0
- autogen/agentchat/group/events/transition_events.py +111 -0
- autogen/agentchat/group/group_tool_executor.py +324 -0
- autogen/agentchat/group/group_utils.py +659 -0
- autogen/agentchat/group/guardrails.py +179 -0
- autogen/agentchat/group/handoffs.py +303 -0
- autogen/agentchat/group/llm_condition.py +93 -0
- autogen/agentchat/group/multi_agent_chat.py +291 -0
- autogen/agentchat/group/on_condition.py +55 -0
- autogen/agentchat/group/on_context_condition.py +51 -0
- autogen/agentchat/group/patterns/__init__.py +18 -0
- autogen/agentchat/group/patterns/auto.py +160 -0
- autogen/agentchat/group/patterns/manual.py +177 -0
- autogen/agentchat/group/patterns/pattern.py +295 -0
- autogen/agentchat/group/patterns/random.py +106 -0
- autogen/agentchat/group/patterns/round_robin.py +117 -0
- autogen/agentchat/group/reply_result.py +24 -0
- autogen/agentchat/group/safeguards/__init__.py +21 -0
- autogen/agentchat/group/safeguards/api.py +241 -0
- autogen/agentchat/group/safeguards/enforcer.py +1158 -0
- autogen/agentchat/group/safeguards/events.py +140 -0
- autogen/agentchat/group/safeguards/validator.py +435 -0
- autogen/agentchat/group/speaker_selection_result.py +41 -0
- autogen/agentchat/group/targets/__init__.py +4 -0
- autogen/agentchat/group/targets/function_target.py +245 -0
- autogen/agentchat/group/targets/group_chat_target.py +133 -0
- autogen/agentchat/group/targets/group_manager_target.py +151 -0
- autogen/agentchat/group/targets/transition_target.py +424 -0
- autogen/agentchat/group/targets/transition_utils.py +6 -0
- autogen/agentchat/groupchat.py +1832 -0
- autogen/agentchat/realtime/__init__.py +3 -0
- autogen/agentchat/realtime/experimental/__init__.py +20 -0
- autogen/agentchat/realtime/experimental/audio_adapters/__init__.py +8 -0
- autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +148 -0
- autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +139 -0
- autogen/agentchat/realtime/experimental/audio_observer.py +42 -0
- autogen/agentchat/realtime/experimental/clients/__init__.py +15 -0
- autogen/agentchat/realtime/experimental/clients/gemini/__init__.py +7 -0
- autogen/agentchat/realtime/experimental/clients/gemini/client.py +274 -0
- autogen/agentchat/realtime/experimental/clients/oai/__init__.py +8 -0
- autogen/agentchat/realtime/experimental/clients/oai/base_client.py +220 -0
- autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +243 -0
- autogen/agentchat/realtime/experimental/clients/oai/utils.py +48 -0
- autogen/agentchat/realtime/experimental/clients/realtime_client.py +191 -0
- autogen/agentchat/realtime/experimental/function_observer.py +84 -0
- autogen/agentchat/realtime/experimental/realtime_agent.py +158 -0
- autogen/agentchat/realtime/experimental/realtime_events.py +42 -0
- autogen/agentchat/realtime/experimental/realtime_observer.py +100 -0
- autogen/agentchat/realtime/experimental/realtime_swarm.py +533 -0
- autogen/agentchat/realtime/experimental/websockets.py +21 -0
- autogen/agentchat/realtime_agent/__init__.py +21 -0
- autogen/agentchat/user_proxy_agent.py +114 -0
- autogen/agentchat/utils.py +206 -0
- autogen/agents/__init__.py +3 -0
- autogen/agents/contrib/__init__.py +10 -0
- autogen/agents/contrib/time/__init__.py +8 -0
- autogen/agents/contrib/time/time_reply_agent.py +74 -0
- autogen/agents/contrib/time/time_tool_agent.py +52 -0
- autogen/agents/experimental/__init__.py +27 -0
- autogen/agents/experimental/deep_research/__init__.py +7 -0
- autogen/agents/experimental/deep_research/deep_research.py +52 -0
- autogen/agents/experimental/discord/__init__.py +7 -0
- autogen/agents/experimental/discord/discord.py +66 -0
- autogen/agents/experimental/document_agent/__init__.py +19 -0
- autogen/agents/experimental/document_agent/chroma_query_engine.py +301 -0
- autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +113 -0
- autogen/agents/experimental/document_agent/document_agent.py +643 -0
- autogen/agents/experimental/document_agent/document_conditions.py +50 -0
- autogen/agents/experimental/document_agent/document_utils.py +376 -0
- autogen/agents/experimental/document_agent/inmemory_query_engine.py +214 -0
- autogen/agents/experimental/document_agent/parser_utils.py +134 -0
- autogen/agents/experimental/document_agent/url_utils.py +417 -0
- autogen/agents/experimental/reasoning/__init__.py +7 -0
- autogen/agents/experimental/reasoning/reasoning_agent.py +1178 -0
- autogen/agents/experimental/slack/__init__.py +7 -0
- autogen/agents/experimental/slack/slack.py +73 -0
- autogen/agents/experimental/telegram/__init__.py +7 -0
- autogen/agents/experimental/telegram/telegram.py +76 -0
- autogen/agents/experimental/websurfer/__init__.py +7 -0
- autogen/agents/experimental/websurfer/websurfer.py +70 -0
- autogen/agents/experimental/wikipedia/__init__.py +7 -0
- autogen/agents/experimental/wikipedia/wikipedia.py +88 -0
- autogen/browser_utils.py +309 -0
- autogen/cache/__init__.py +10 -0
- autogen/cache/abstract_cache_base.py +71 -0
- autogen/cache/cache.py +203 -0
- autogen/cache/cache_factory.py +88 -0
- autogen/cache/cosmos_db_cache.py +144 -0
- autogen/cache/disk_cache.py +97 -0
- autogen/cache/in_memory_cache.py +54 -0
- autogen/cache/redis_cache.py +119 -0
- autogen/code_utils.py +598 -0
- autogen/coding/__init__.py +30 -0
- autogen/coding/base.py +120 -0
- autogen/coding/docker_commandline_code_executor.py +283 -0
- autogen/coding/factory.py +56 -0
- autogen/coding/func_with_reqs.py +203 -0
- autogen/coding/jupyter/__init__.py +23 -0
- autogen/coding/jupyter/base.py +36 -0
- autogen/coding/jupyter/docker_jupyter_server.py +160 -0
- autogen/coding/jupyter/embedded_ipython_code_executor.py +182 -0
- autogen/coding/jupyter/import_utils.py +82 -0
- autogen/coding/jupyter/jupyter_client.py +224 -0
- autogen/coding/jupyter/jupyter_code_executor.py +154 -0
- autogen/coding/jupyter/local_jupyter_server.py +164 -0
- autogen/coding/local_commandline_code_executor.py +341 -0
- autogen/coding/markdown_code_extractor.py +44 -0
- autogen/coding/utils.py +55 -0
- autogen/coding/yepcode_code_executor.py +197 -0
- autogen/doc_utils.py +35 -0
- autogen/environments/__init__.py +10 -0
- autogen/environments/docker_python_environment.py +365 -0
- autogen/environments/python_environment.py +125 -0
- autogen/environments/system_python_environment.py +85 -0
- autogen/environments/venv_python_environment.py +220 -0
- autogen/environments/working_directory.py +74 -0
- autogen/events/__init__.py +7 -0
- autogen/events/agent_events.py +1016 -0
- autogen/events/base_event.py +100 -0
- autogen/events/client_events.py +168 -0
- autogen/events/helpers.py +44 -0
- autogen/events/print_event.py +45 -0
- autogen/exception_utils.py +73 -0
- autogen/extensions/__init__.py +5 -0
- autogen/fast_depends/__init__.py +16 -0
- autogen/fast_depends/_compat.py +75 -0
- autogen/fast_depends/core/__init__.py +14 -0
- autogen/fast_depends/core/build.py +206 -0
- autogen/fast_depends/core/model.py +527 -0
- autogen/fast_depends/dependencies/__init__.py +15 -0
- autogen/fast_depends/dependencies/model.py +30 -0
- autogen/fast_depends/dependencies/provider.py +40 -0
- autogen/fast_depends/library/__init__.py +10 -0
- autogen/fast_depends/library/model.py +46 -0
- autogen/fast_depends/py.typed +6 -0
- autogen/fast_depends/schema.py +66 -0
- autogen/fast_depends/use.py +272 -0
- autogen/fast_depends/utils.py +177 -0
- autogen/formatting_utils.py +83 -0
- autogen/function_utils.py +13 -0
- autogen/graph_utils.py +173 -0
- autogen/import_utils.py +539 -0
- autogen/interop/__init__.py +22 -0
- autogen/interop/crewai/__init__.py +7 -0
- autogen/interop/crewai/crewai.py +88 -0
- autogen/interop/interoperability.py +71 -0
- autogen/interop/interoperable.py +46 -0
- autogen/interop/langchain/__init__.py +8 -0
- autogen/interop/langchain/langchain_chat_model_factory.py +156 -0
- autogen/interop/langchain/langchain_tool.py +78 -0
- autogen/interop/litellm/__init__.py +7 -0
- autogen/interop/litellm/litellm_config_factory.py +178 -0
- autogen/interop/pydantic_ai/__init__.py +7 -0
- autogen/interop/pydantic_ai/pydantic_ai.py +172 -0
- autogen/interop/registry.py +70 -0
- autogen/io/__init__.py +15 -0
- autogen/io/base.py +151 -0
- autogen/io/console.py +56 -0
- autogen/io/processors/__init__.py +12 -0
- autogen/io/processors/base.py +21 -0
- autogen/io/processors/console_event_processor.py +61 -0
- autogen/io/run_response.py +294 -0
- autogen/io/thread_io_stream.py +63 -0
- autogen/io/websockets.py +214 -0
- autogen/json_utils.py +42 -0
- autogen/llm_clients/MIGRATION_TO_V2.md +782 -0
- autogen/llm_clients/__init__.py +77 -0
- autogen/llm_clients/client_v2.py +122 -0
- autogen/llm_clients/models/__init__.py +55 -0
- autogen/llm_clients/models/content_blocks.py +389 -0
- autogen/llm_clients/models/unified_message.py +145 -0
- autogen/llm_clients/models/unified_response.py +83 -0
- autogen/llm_clients/openai_completions_client.py +444 -0
- autogen/llm_config/__init__.py +11 -0
- autogen/llm_config/client.py +59 -0
- autogen/llm_config/config.py +461 -0
- autogen/llm_config/entry.py +169 -0
- autogen/llm_config/types.py +37 -0
- autogen/llm_config/utils.py +223 -0
- autogen/logger/__init__.py +11 -0
- autogen/logger/base_logger.py +129 -0
- autogen/logger/file_logger.py +262 -0
- autogen/logger/logger_factory.py +42 -0
- autogen/logger/logger_utils.py +57 -0
- autogen/logger/sqlite_logger.py +524 -0
- autogen/math_utils.py +338 -0
- autogen/mcp/__init__.py +7 -0
- autogen/mcp/__main__.py +78 -0
- autogen/mcp/helpers.py +45 -0
- autogen/mcp/mcp_client.py +349 -0
- autogen/mcp/mcp_proxy/__init__.py +19 -0
- autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +62 -0
- autogen/mcp/mcp_proxy/mcp_proxy.py +577 -0
- autogen/mcp/mcp_proxy/operation_grouping.py +166 -0
- autogen/mcp/mcp_proxy/operation_renaming.py +110 -0
- autogen/mcp/mcp_proxy/patch_fastapi_code_generator.py +98 -0
- autogen/mcp/mcp_proxy/security.py +399 -0
- autogen/mcp/mcp_proxy/security_schema_visitor.py +37 -0
- autogen/messages/__init__.py +7 -0
- autogen/messages/agent_messages.py +946 -0
- autogen/messages/base_message.py +108 -0
- autogen/messages/client_messages.py +172 -0
- autogen/messages/print_message.py +48 -0
- autogen/oai/__init__.py +61 -0
- autogen/oai/anthropic.py +1516 -0
- autogen/oai/bedrock.py +800 -0
- autogen/oai/cerebras.py +302 -0
- autogen/oai/client.py +1658 -0
- autogen/oai/client_utils.py +196 -0
- autogen/oai/cohere.py +494 -0
- autogen/oai/gemini.py +1045 -0
- autogen/oai/gemini_types.py +156 -0
- autogen/oai/groq.py +319 -0
- autogen/oai/mistral.py +311 -0
- autogen/oai/oai_models/__init__.py +23 -0
- autogen/oai/oai_models/_models.py +16 -0
- autogen/oai/oai_models/chat_completion.py +86 -0
- autogen/oai/oai_models/chat_completion_audio.py +32 -0
- autogen/oai/oai_models/chat_completion_message.py +97 -0
- autogen/oai/oai_models/chat_completion_message_tool_call.py +60 -0
- autogen/oai/oai_models/chat_completion_token_logprob.py +62 -0
- autogen/oai/oai_models/completion_usage.py +59 -0
- autogen/oai/ollama.py +657 -0
- autogen/oai/openai_responses.py +451 -0
- autogen/oai/openai_utils.py +897 -0
- autogen/oai/together.py +387 -0
- autogen/remote/__init__.py +18 -0
- autogen/remote/agent.py +199 -0
- autogen/remote/agent_service.py +197 -0
- autogen/remote/errors.py +17 -0
- autogen/remote/httpx_client_factory.py +131 -0
- autogen/remote/protocol.py +37 -0
- autogen/remote/retry.py +102 -0
- autogen/remote/runtime.py +96 -0
- autogen/retrieve_utils.py +490 -0
- autogen/runtime_logging.py +161 -0
- autogen/testing/__init__.py +12 -0
- autogen/testing/messages.py +45 -0
- autogen/testing/test_agent.py +111 -0
- autogen/token_count_utils.py +280 -0
- autogen/tools/__init__.py +20 -0
- autogen/tools/contrib/__init__.py +9 -0
- autogen/tools/contrib/time/__init__.py +7 -0
- autogen/tools/contrib/time/time.py +40 -0
- autogen/tools/dependency_injection.py +249 -0
- autogen/tools/experimental/__init__.py +54 -0
- autogen/tools/experimental/browser_use/__init__.py +7 -0
- autogen/tools/experimental/browser_use/browser_use.py +154 -0
- autogen/tools/experimental/code_execution/__init__.py +7 -0
- autogen/tools/experimental/code_execution/python_code_execution.py +86 -0
- autogen/tools/experimental/crawl4ai/__init__.py +7 -0
- autogen/tools/experimental/crawl4ai/crawl4ai.py +150 -0
- autogen/tools/experimental/deep_research/__init__.py +7 -0
- autogen/tools/experimental/deep_research/deep_research.py +329 -0
- autogen/tools/experimental/duckduckgo/__init__.py +7 -0
- autogen/tools/experimental/duckduckgo/duckduckgo_search.py +103 -0
- autogen/tools/experimental/firecrawl/__init__.py +7 -0
- autogen/tools/experimental/firecrawl/firecrawl_tool.py +836 -0
- autogen/tools/experimental/google/__init__.py +14 -0
- autogen/tools/experimental/google/authentication/__init__.py +11 -0
- autogen/tools/experimental/google/authentication/credentials_hosted_provider.py +43 -0
- autogen/tools/experimental/google/authentication/credentials_local_provider.py +91 -0
- autogen/tools/experimental/google/authentication/credentials_provider.py +35 -0
- autogen/tools/experimental/google/drive/__init__.py +9 -0
- autogen/tools/experimental/google/drive/drive_functions.py +124 -0
- autogen/tools/experimental/google/drive/toolkit.py +88 -0
- autogen/tools/experimental/google/model.py +17 -0
- autogen/tools/experimental/google/toolkit_protocol.py +19 -0
- autogen/tools/experimental/google_search/__init__.py +8 -0
- autogen/tools/experimental/google_search/google_search.py +93 -0
- autogen/tools/experimental/google_search/youtube_search.py +181 -0
- autogen/tools/experimental/messageplatform/__init__.py +17 -0
- autogen/tools/experimental/messageplatform/discord/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/discord/discord.py +284 -0
- autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/slack/slack.py +385 -0
- autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/telegram/telegram.py +271 -0
- autogen/tools/experimental/perplexity/__init__.py +7 -0
- autogen/tools/experimental/perplexity/perplexity_search.py +249 -0
- autogen/tools/experimental/reliable/__init__.py +10 -0
- autogen/tools/experimental/reliable/reliable.py +1311 -0
- autogen/tools/experimental/searxng/__init__.py +7 -0
- autogen/tools/experimental/searxng/searxng_search.py +142 -0
- autogen/tools/experimental/tavily/__init__.py +7 -0
- autogen/tools/experimental/tavily/tavily_search.py +176 -0
- autogen/tools/experimental/web_search_preview/__init__.py +7 -0
- autogen/tools/experimental/web_search_preview/web_search_preview.py +120 -0
- autogen/tools/experimental/wikipedia/__init__.py +7 -0
- autogen/tools/experimental/wikipedia/wikipedia.py +284 -0
- autogen/tools/function_utils.py +412 -0
- autogen/tools/tool.py +188 -0
- autogen/tools/toolkit.py +86 -0
- autogen/types.py +29 -0
- autogen/version.py +7 -0
- templates/client_template/main.jinja2 +72 -0
- templates/config_template/config.jinja2 +7 -0
- templates/main.jinja2 +61 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import inspect
|
|
8
|
+
from collections.abc import Callable
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, Field
|
|
12
|
+
|
|
13
|
+
from ...agent import Agent
|
|
14
|
+
from ..context_variables import ContextVariables
|
|
15
|
+
from ..speaker_selection_result import SpeakerSelectionResult
|
|
16
|
+
from .transition_target import AgentNameTarget, AgentTarget, RevertToUserTarget, StayTarget, TransitionTarget
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from ...conversable_agent import ConversableAgent
|
|
20
|
+
from ...groupchat import GroupChat
|
|
21
|
+
|
|
22
|
+
__all__ = ["FunctionTarget", "FunctionTargetMessage", "FunctionTargetResult", "broadcast"]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FunctionTargetMessage(BaseModel):
|
|
26
|
+
"""Message and target that can be sent as part of the FunctionTargetResult.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
content: The content of the message to be sent.
|
|
30
|
+
msg_target: The agent to whom the message is to be sent.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
content: str
|
|
34
|
+
msg_target: Agent
|
|
35
|
+
|
|
36
|
+
class Config:
|
|
37
|
+
arbitrary_types_allowed = True
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class FunctionTargetResult(BaseModel):
|
|
41
|
+
"""Result of a function handoff that is used to provide the return message and the target to transition to.
|
|
42
|
+
|
|
43
|
+
Attributes:
|
|
44
|
+
messages: Optional list of messages to be broadcast to specific agents, or a single string message.
|
|
45
|
+
context_variables: Optional updated context variables that will be applied to the group chat context variables.
|
|
46
|
+
target: The next target to transition to.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
messages: list[FunctionTargetMessage] | str | None = None
|
|
50
|
+
context_variables: ContextVariables | None = None
|
|
51
|
+
target: TransitionTarget
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def construct_broadcast_messages_list(
|
|
55
|
+
messages: list[FunctionTargetMessage] | str,
|
|
56
|
+
group_chat: GroupChat,
|
|
57
|
+
current_agent: ConversableAgent,
|
|
58
|
+
target: TransitionTarget,
|
|
59
|
+
user_agent: ConversableAgent | None = None,
|
|
60
|
+
) -> list[FunctionTargetMessage]:
|
|
61
|
+
"""Construct a list of FunctionTargetMessage from input messages and target."""
|
|
62
|
+
if isinstance(messages, str):
|
|
63
|
+
if isinstance(target, (AgentTarget, AgentNameTarget)):
|
|
64
|
+
next_target = target.agent_name
|
|
65
|
+
for agent in group_chat.agents:
|
|
66
|
+
if agent.name == next_target:
|
|
67
|
+
messages_list = [FunctionTargetMessage(content=messages, msg_target=agent)]
|
|
68
|
+
break
|
|
69
|
+
else:
|
|
70
|
+
raise ValueError(f"No agent found with in the group chat matching the target agent name {next_target}.")
|
|
71
|
+
elif isinstance(target, RevertToUserTarget) and user_agent is not None:
|
|
72
|
+
messages_list = [FunctionTargetMessage(content=messages, msg_target=user_agent)]
|
|
73
|
+
elif isinstance(target, StayTarget):
|
|
74
|
+
messages_list = [FunctionTargetMessage(content=messages, msg_target=current_agent)]
|
|
75
|
+
else:
|
|
76
|
+
# Default to current agent if no target is not agent-based is found
|
|
77
|
+
messages_list = [FunctionTargetMessage(content=messages, msg_target=current_agent)]
|
|
78
|
+
else:
|
|
79
|
+
messages_list = messages
|
|
80
|
+
return messages_list
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def broadcast(
|
|
84
|
+
messages: list[FunctionTargetMessage] | str,
|
|
85
|
+
group_chat: GroupChat,
|
|
86
|
+
current_agent: ConversableAgent,
|
|
87
|
+
fn_name: str,
|
|
88
|
+
target: TransitionTarget,
|
|
89
|
+
user_agent: ConversableAgent | None = None,
|
|
90
|
+
) -> None:
|
|
91
|
+
"""Broadcast message(s) to their target agent."""
|
|
92
|
+
messages_list = construct_broadcast_messages_list(messages, group_chat, current_agent, target, user_agent)
|
|
93
|
+
|
|
94
|
+
for message in messages_list:
|
|
95
|
+
content = message.content
|
|
96
|
+
broadcast = {
|
|
97
|
+
"role": "system",
|
|
98
|
+
"name": f"{fn_name}",
|
|
99
|
+
"content": f"[FUNCTION_HANDOFF] - Reply from function {fn_name}: \n\n {content}",
|
|
100
|
+
}
|
|
101
|
+
if hasattr(current_agent, "_group_manager") and current_agent._group_manager is not None:
|
|
102
|
+
current_agent._group_manager.send(
|
|
103
|
+
broadcast,
|
|
104
|
+
message.msg_target,
|
|
105
|
+
request_reply=False,
|
|
106
|
+
silent=False,
|
|
107
|
+
)
|
|
108
|
+
else:
|
|
109
|
+
raise ValueError("Current agent must have a group manager to broadcast messages.")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def validate_fn_sig(
|
|
113
|
+
incoming_fn: Callable[..., FunctionTargetResult],
|
|
114
|
+
extra_args: dict[str, Any],
|
|
115
|
+
) -> None:
|
|
116
|
+
"""
|
|
117
|
+
Validate a user-defined afterwork_function signature.
|
|
118
|
+
|
|
119
|
+
Rules:
|
|
120
|
+
1. Must have at least two positional parameters (whatever their names).
|
|
121
|
+
2. All provided extra_args must exist in the function signature (unless **kwargs is present).
|
|
122
|
+
3. All additional required (non-default) params beyond the first two must be satisfied via extra_args.
|
|
123
|
+
"""
|
|
124
|
+
sig = inspect.signature(incoming_fn)
|
|
125
|
+
params = list(sig.parameters.values())
|
|
126
|
+
|
|
127
|
+
# 1️⃣ Must have at least two positional parameters (whatever names)
|
|
128
|
+
if len(params) < 2:
|
|
129
|
+
raise ValueError(
|
|
130
|
+
f"Function '{incoming_fn.__name__}' must accept at least two positional parameters: "
|
|
131
|
+
f"(output, ctx). Current: {[p.name for p in params]}"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# 2️⃣ Detect **kwargs
|
|
135
|
+
has_kwargs = any(p.kind == inspect.Parameter.VAR_KEYWORD for p in params)
|
|
136
|
+
|
|
137
|
+
# Build list of extra (non-core) params after the first two
|
|
138
|
+
extra_params = [
|
|
139
|
+
p for p in params[2:] if p.kind not in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD)
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
# 3️⃣ If **kwargs not present, check for invalid extra_args
|
|
143
|
+
if not has_kwargs:
|
|
144
|
+
valid_names = {p.name for p in params}
|
|
145
|
+
invalid_keys = [k for k in extra_args if k not in valid_names]
|
|
146
|
+
if invalid_keys:
|
|
147
|
+
raise ValueError(
|
|
148
|
+
f"Invalid extra_args for function '{incoming_fn.__name__}': {invalid_keys}. "
|
|
149
|
+
f"Allowed parameters are: {[p.name for p in params]}."
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# 4️⃣ Check for missing required params (no defaults) among the extra ones
|
|
153
|
+
missing_keys = [p.name for p in extra_params if p.default is p.empty and p.name not in extra_args]
|
|
154
|
+
|
|
155
|
+
if missing_keys:
|
|
156
|
+
raise ValueError(
|
|
157
|
+
f"Missing required extra_args for function '{incoming_fn.__name__}': {missing_keys}. "
|
|
158
|
+
f"You must supply them via `extra_args`."
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class FunctionTarget(TransitionTarget):
|
|
163
|
+
"""Transition target that invokes a tool function with (prev_output, context).
|
|
164
|
+
|
|
165
|
+
The function must return a FunctionTargetResult object that includes the next target to transition to.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
fn_name: str = Field(...)
|
|
169
|
+
fn: Callable[..., FunctionTargetResult] = Field(..., repr=False)
|
|
170
|
+
extra_args: dict[str, Any] = Field(default_factory=dict)
|
|
171
|
+
|
|
172
|
+
def __init__(
|
|
173
|
+
self,
|
|
174
|
+
incoming_fn: Callable[..., FunctionTargetResult],
|
|
175
|
+
*,
|
|
176
|
+
extra_args: dict[str, Any] | None = None,
|
|
177
|
+
**kwargs: Any,
|
|
178
|
+
) -> None:
|
|
179
|
+
if callable(incoming_fn):
|
|
180
|
+
extra_args = extra_args or {}
|
|
181
|
+
|
|
182
|
+
validate_fn_sig(incoming_fn, extra_args)
|
|
183
|
+
|
|
184
|
+
super().__init__(fn_name=incoming_fn.__name__, fn=incoming_fn, extra_args=extra_args, **kwargs)
|
|
185
|
+
else:
|
|
186
|
+
raise ValueError(
|
|
187
|
+
"FunctionTarget must be initialized with a callable function as the first argument or 'fn' keyword argument."
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def can_resolve_for_speaker_selection(self) -> bool:
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
def resolve(
|
|
194
|
+
self,
|
|
195
|
+
groupchat: GroupChat,
|
|
196
|
+
current_agent: ConversableAgent,
|
|
197
|
+
user_agent: ConversableAgent | None,
|
|
198
|
+
) -> SpeakerSelectionResult:
|
|
199
|
+
"""Invoke the function, update context variables (optional), broadcast messages (optional), and return the next target to transition to."""
|
|
200
|
+
last_message = (
|
|
201
|
+
groupchat.messages[-1]["content"] if groupchat.messages and "content" in groupchat.messages[-1] else ""
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Run the function to get the FunctionTargetResult
|
|
205
|
+
function_target_result = self.fn(
|
|
206
|
+
last_message,
|
|
207
|
+
current_agent.context_variables,
|
|
208
|
+
**self.extra_args,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
if not isinstance(function_target_result, FunctionTargetResult):
|
|
212
|
+
raise ValueError("FunctionTarget function must return a FunctionTargetResult object.")
|
|
213
|
+
|
|
214
|
+
if function_target_result.context_variables:
|
|
215
|
+
# Update the group's Context Variables if the function returned any
|
|
216
|
+
current_agent.context_variables.update(function_target_result.context_variables.to_dict())
|
|
217
|
+
|
|
218
|
+
if function_target_result.messages:
|
|
219
|
+
# If we have messages, we need to broadcast them to the appropriate agent based on the target
|
|
220
|
+
broadcast(
|
|
221
|
+
function_target_result.messages,
|
|
222
|
+
groupchat,
|
|
223
|
+
current_agent,
|
|
224
|
+
self.fn_name,
|
|
225
|
+
function_target_result.target,
|
|
226
|
+
user_agent,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
# Resolve and return the next target
|
|
230
|
+
return function_target_result.target.resolve(groupchat, current_agent, user_agent)
|
|
231
|
+
|
|
232
|
+
def display_name(self) -> str:
|
|
233
|
+
return self.fn_name
|
|
234
|
+
|
|
235
|
+
def normalized_name(self) -> str:
|
|
236
|
+
return self.fn_name.replace(" ", "_")
|
|
237
|
+
|
|
238
|
+
def __str__(self) -> str:
|
|
239
|
+
return f"Transfer to tool {self.fn_name}"
|
|
240
|
+
|
|
241
|
+
def needs_agent_wrapper(self) -> bool:
|
|
242
|
+
return False
|
|
243
|
+
|
|
244
|
+
def create_wrapper_agent(self, parent_agent: ConversableAgent, index: int) -> ConversableAgent:
|
|
245
|
+
raise NotImplementedError("FunctionTarget is executed inline and needs no wrapper")
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from ....doc_utils import export_module
|
|
10
|
+
from ...agent import Agent
|
|
11
|
+
from ..speaker_selection_result import SpeakerSelectionResult
|
|
12
|
+
from .transition_target import AgentTarget, TransitionTarget
|
|
13
|
+
from .transition_utils import __AGENT_WRAPPER_PREFIX__
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from ...conversable_agent import ConversableAgent
|
|
17
|
+
from ...groupchat import GroupChat
|
|
18
|
+
from ..patterns.pattern import Pattern
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__all__ = ["GroupChatConfig", "GroupChatTarget"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@export_module("autogen.agentchat.group")
|
|
25
|
+
class GroupChatConfig(BaseModel):
|
|
26
|
+
"""Configuration for a group chat transition target.
|
|
27
|
+
|
|
28
|
+
Note: If context_variables are not passed in, the outer context variables will be passed in
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
pattern: "Pattern"
|
|
32
|
+
messages: list[dict[str, Any]] | str
|
|
33
|
+
max_rounds: int = 20
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@export_module("autogen.agentchat.group")
|
|
37
|
+
class GroupChatTarget(TransitionTarget):
|
|
38
|
+
"""Target that represents a group chat."""
|
|
39
|
+
|
|
40
|
+
group_chat_config: GroupChatConfig
|
|
41
|
+
|
|
42
|
+
def can_resolve_for_speaker_selection(self) -> bool:
|
|
43
|
+
"""Check if the target can resolve for speaker selection. For GroupChatTarget the chat must be encapsulated into an agent."""
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
def resolve(
|
|
47
|
+
self,
|
|
48
|
+
groupchat: "GroupChat",
|
|
49
|
+
current_agent: "ConversableAgent",
|
|
50
|
+
user_agent: Optional["ConversableAgent"],
|
|
51
|
+
) -> SpeakerSelectionResult:
|
|
52
|
+
"""Resolve to the nested chat configuration."""
|
|
53
|
+
raise NotImplementedError(
|
|
54
|
+
"GroupChatTarget does not support the resolve method. An agent should be used to encapsulate this nested chat and then the target changed to an AgentTarget."
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def display_name(self) -> str:
|
|
58
|
+
"""Get the display name for the target."""
|
|
59
|
+
return "a group chat"
|
|
60
|
+
|
|
61
|
+
def normalized_name(self) -> str:
|
|
62
|
+
"""Get a normalized name for the target that has no spaces, used for function calling."""
|
|
63
|
+
return "group_chat"
|
|
64
|
+
|
|
65
|
+
def __str__(self) -> str:
|
|
66
|
+
"""String representation for AgentTarget, can be shown as a function call message."""
|
|
67
|
+
return "Transfer to group chat"
|
|
68
|
+
|
|
69
|
+
def needs_agent_wrapper(self) -> bool:
|
|
70
|
+
"""Check if the target needs to be wrapped in an agent. GroupChatTarget must be wrapped in an agent."""
|
|
71
|
+
return True
|
|
72
|
+
|
|
73
|
+
def create_wrapper_agent(self, parent_agent: "ConversableAgent", index: int) -> "ConversableAgent":
|
|
74
|
+
"""Create a wrapper agent for the group chat."""
|
|
75
|
+
from autogen.agentchat import initiate_group_chat
|
|
76
|
+
|
|
77
|
+
from ...conversable_agent import ConversableAgent # to avoid circular import
|
|
78
|
+
|
|
79
|
+
# Create the wrapper agent with a name that identifies it as a wrapped group chat
|
|
80
|
+
group_chat_agent = ConversableAgent(
|
|
81
|
+
name=f"{__AGENT_WRAPPER_PREFIX__}group_{parent_agent.name}_{index + 1}",
|
|
82
|
+
# Copy LLM config from parent agent to ensure it can generate replies if needed
|
|
83
|
+
llm_config=parent_agent.llm_config,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Store the config directly on the agent
|
|
87
|
+
group_chat_agent._group_chat_config = self.group_chat_config # type: ignore[attr-defined]
|
|
88
|
+
|
|
89
|
+
# Define the reply function that will run the group chat
|
|
90
|
+
def group_chat_reply(
|
|
91
|
+
agent: "ConversableAgent",
|
|
92
|
+
messages: list[dict[str, Any]] | None = None,
|
|
93
|
+
sender: Optional["Agent"] = None,
|
|
94
|
+
config: Any | None = None,
|
|
95
|
+
) -> tuple[bool, dict[str, Any] | None]:
|
|
96
|
+
"""Run the inner group chat and return its results as a reply."""
|
|
97
|
+
# Get the configuration stored directly on the agent
|
|
98
|
+
group_config = agent._group_chat_config # type: ignore[attr-defined]
|
|
99
|
+
|
|
100
|
+
# Pull through the second last message from the outer chat (the last message will be the handoff message)
|
|
101
|
+
# This may need work to make sure we get the right message(s) from the outer chat
|
|
102
|
+
message = (
|
|
103
|
+
messages[-2]["content"]
|
|
104
|
+
if messages and len(messages) >= 2 and "content" in messages[-2]
|
|
105
|
+
else "No message to pass through."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
# Run the group chat with direct agent references from the config
|
|
110
|
+
result, _, _ = initiate_group_chat(
|
|
111
|
+
pattern=group_config.pattern,
|
|
112
|
+
messages=message,
|
|
113
|
+
max_rounds=group_config.max_rounds,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Return the summary from the chat result summary
|
|
117
|
+
return True, {"content": result.summary}
|
|
118
|
+
|
|
119
|
+
except Exception as e:
|
|
120
|
+
# Handle any errors during execution
|
|
121
|
+
return True, {"content": f"Error running group chat: {str(e)}"}
|
|
122
|
+
|
|
123
|
+
# Register the reply function with the wrapper agent
|
|
124
|
+
group_chat_agent.register_reply(
|
|
125
|
+
trigger=[ConversableAgent, None],
|
|
126
|
+
reply_func=group_chat_reply,
|
|
127
|
+
remove_other_reply_funcs=True, # Use only this reply function
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# After the group chat completes, transition back to the parent agent
|
|
131
|
+
group_chat_agent.handoffs.set_after_work(AgentTarget(parent_agent))
|
|
132
|
+
|
|
133
|
+
return group_chat_agent
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, field_validator
|
|
8
|
+
|
|
9
|
+
from ....doc_utils import export_module
|
|
10
|
+
from ..context_str import ContextStr
|
|
11
|
+
from ..group_tool_executor import GroupToolExecutor
|
|
12
|
+
from ..speaker_selection_result import SpeakerSelectionResult
|
|
13
|
+
from .transition_target import TransitionTarget
|
|
14
|
+
from .transition_utils import __AGENT_WRAPPER_PREFIX__
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
# Avoid circular import
|
|
18
|
+
from ...conversable_agent import ConversableAgent
|
|
19
|
+
from ...groupchat import GroupChat
|
|
20
|
+
|
|
21
|
+
__all__ = ["GroupManagerTarget"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def prepare_groupchat_auto_speaker(
|
|
25
|
+
groupchat: "GroupChat",
|
|
26
|
+
last_group_agent: "ConversableAgent",
|
|
27
|
+
group_chat_manager_selection_msg: Any | None,
|
|
28
|
+
) -> None:
|
|
29
|
+
"""Prepare the group chat for auto speaker selection, includes updating or restore the groupchat speaker selection message.
|
|
30
|
+
|
|
31
|
+
Tool Executor and wrapped agents will be removed from the available agents list.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
groupchat (GroupChat): GroupChat instance.
|
|
35
|
+
last_group_agent ("ConversableAgent"): The last group agent for which the LLM config is used
|
|
36
|
+
group_chat_manager_selection_msg (GroupManagerSelectionMessage): Optional message to use for the agent selection (in internal group chat).
|
|
37
|
+
"""
|
|
38
|
+
from ...groupchat import SELECT_SPEAKER_PROMPT_TEMPLATE
|
|
39
|
+
|
|
40
|
+
def substitute_agentlist(template: str) -> str:
|
|
41
|
+
# Run through group chat's string substitution first for {agentlist}
|
|
42
|
+
# We need to do this so that the next substitution doesn't fail with agentlist
|
|
43
|
+
# and we can remove the tool executor and wrapped chats from the available agents list
|
|
44
|
+
agent_list = [
|
|
45
|
+
agent
|
|
46
|
+
for agent in groupchat.agents
|
|
47
|
+
if not isinstance(agent, GroupToolExecutor) and not agent.name.startswith(__AGENT_WRAPPER_PREFIX__)
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
groupchat.select_speaker_prompt_template = template
|
|
51
|
+
return groupchat.select_speaker_prompt(agent_list)
|
|
52
|
+
|
|
53
|
+
# Use the default speaker selection prompt if one is not specified, otherwise use the specified one
|
|
54
|
+
groupchat.select_speaker_prompt_template = substitute_agentlist(
|
|
55
|
+
SELECT_SPEAKER_PROMPT_TEMPLATE
|
|
56
|
+
if group_chat_manager_selection_msg is None
|
|
57
|
+
else group_chat_manager_selection_msg.get_message(last_group_agent)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# GroupManagerSelectionMessage protocol and implementations
|
|
62
|
+
@export_module("autogen.agentchat.group")
|
|
63
|
+
class GroupManagerSelectionMessage(BaseModel):
|
|
64
|
+
"""Base class for all GroupManager selection message types."""
|
|
65
|
+
|
|
66
|
+
def get_message(self, agent: "ConversableAgent") -> str:
|
|
67
|
+
"""Get the formatted message."""
|
|
68
|
+
raise NotImplementedError("Requires subclasses to implement.")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@export_module("autogen.agentchat.group")
|
|
72
|
+
class GroupManagerSelectionMessageString(GroupManagerSelectionMessage):
|
|
73
|
+
"""Selection message that uses a plain string template."""
|
|
74
|
+
|
|
75
|
+
message: str
|
|
76
|
+
|
|
77
|
+
def get_message(self, agent: "ConversableAgent") -> str:
|
|
78
|
+
"""Get the message string."""
|
|
79
|
+
return self.message
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@export_module("autogen.agentchat.group")
|
|
83
|
+
class GroupManagerSelectionMessageContextStr(GroupManagerSelectionMessage):
|
|
84
|
+
"""Selection message that uses a ContextStr template."""
|
|
85
|
+
|
|
86
|
+
context_str_template: str
|
|
87
|
+
|
|
88
|
+
# We will replace {agentlist} with another term and return it later for use with the internal group chat auto speaker selection
|
|
89
|
+
# Otherwise our format will fail
|
|
90
|
+
@field_validator("context_str_template", mode="before")
|
|
91
|
+
def _replace_agentlist_placeholder(cls: type["GroupManagerSelectionMessageContextStr"], v: Any) -> str | Any: # noqa: N805
|
|
92
|
+
"""Replace {agentlist} placeholder before validation/assignment."""
|
|
93
|
+
if isinstance(v, str):
|
|
94
|
+
if "{agentlist}" in v:
|
|
95
|
+
return v.replace("{agentlist}", "<<agent_list>>") # Perform the replacement
|
|
96
|
+
else:
|
|
97
|
+
return v # If no replacement is needed, return the original value
|
|
98
|
+
return ""
|
|
99
|
+
|
|
100
|
+
def get_message(self, agent: "ConversableAgent") -> str:
|
|
101
|
+
"""Get the formatted message with context variables substituted."""
|
|
102
|
+
context_str = ContextStr(template=self.context_str_template)
|
|
103
|
+
format_result = context_str.format(agent.context_variables)
|
|
104
|
+
if format_result is None:
|
|
105
|
+
return ""
|
|
106
|
+
|
|
107
|
+
return format_result.replace(
|
|
108
|
+
"<<agent_list>>", "{agentlist}"
|
|
109
|
+
) # Restore agentlist so it can be substituted by the internal group chat auto speaker selection
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class GroupManagerTarget(TransitionTarget):
|
|
113
|
+
"""Target that represents an agent by name."""
|
|
114
|
+
|
|
115
|
+
selection_message: GroupManagerSelectionMessage | None = None
|
|
116
|
+
|
|
117
|
+
def can_resolve_for_speaker_selection(self) -> bool:
|
|
118
|
+
"""Check if the target can resolve for speaker selection."""
|
|
119
|
+
return True
|
|
120
|
+
|
|
121
|
+
def resolve(
|
|
122
|
+
self,
|
|
123
|
+
groupchat: "GroupChat",
|
|
124
|
+
current_agent: "ConversableAgent",
|
|
125
|
+
user_agent: Optional["ConversableAgent"],
|
|
126
|
+
) -> SpeakerSelectionResult:
|
|
127
|
+
"""Resolve to the speaker selection for the group."""
|
|
128
|
+
if self.selection_message is not None:
|
|
129
|
+
prepare_groupchat_auto_speaker(groupchat, current_agent, self.selection_message)
|
|
130
|
+
|
|
131
|
+
return SpeakerSelectionResult(speaker_selection_method="auto")
|
|
132
|
+
|
|
133
|
+
def display_name(self) -> str:
|
|
134
|
+
"""Get the display name for the target."""
|
|
135
|
+
return "the group manager"
|
|
136
|
+
|
|
137
|
+
def normalized_name(self) -> str:
|
|
138
|
+
"""Get a normalized name for the target that has no spaces, used for function calling"""
|
|
139
|
+
return self.display_name()
|
|
140
|
+
|
|
141
|
+
def __str__(self) -> str:
|
|
142
|
+
"""String representation for AgentTarget, can be shown as a function call message."""
|
|
143
|
+
return "Transfer to the group manager"
|
|
144
|
+
|
|
145
|
+
def needs_agent_wrapper(self) -> bool:
|
|
146
|
+
"""Check if the target needs to be wrapped in an agent."""
|
|
147
|
+
return False
|
|
148
|
+
|
|
149
|
+
def create_wrapper_agent(self, parent_agent: "ConversableAgent", index: int) -> "ConversableAgent":
|
|
150
|
+
"""Create a wrapper agent for the target if needed."""
|
|
151
|
+
raise NotImplementedError("GroupManagerTarget does not require wrapping in an agent.")
|