ag2 0.9.1a1__py3-none-any.whl → 0.9.1.post0__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.
Potentially problematic release.
This version of ag2 might be problematic. Click here for more details.
- {ag2-0.9.1a1.dist-info → ag2-0.9.1.post0.dist-info}/METADATA +264 -73
- ag2-0.9.1.post0.dist-info/RECORD +392 -0
- {ag2-0.9.1a1.dist-info → ag2-0.9.1.post0.dist-info}/WHEEL +1 -2
- autogen/__init__.py +89 -0
- autogen/_website/__init__.py +3 -0
- autogen/_website/generate_api_references.py +427 -0
- autogen/_website/generate_mkdocs.py +1174 -0
- autogen/_website/notebook_processor.py +476 -0
- autogen/_website/process_notebooks.py +656 -0
- autogen/_website/utils.py +412 -0
- autogen/agentchat/__init__.py +44 -0
- autogen/agentchat/agent.py +182 -0
- autogen/agentchat/assistant_agent.py +85 -0
- autogen/agentchat/chat.py +309 -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 +429 -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 +566 -0
- autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
- autogen/agentchat/contrib/capabilities/vision_capability.py +214 -0
- autogen/agentchat/contrib/captainagent/__init__.py +9 -0
- autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
- autogen/agentchat/contrib/captainagent/captainagent.py +512 -0
- autogen/agentchat/contrib/captainagent/tool_retriever.py +335 -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 +170 -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 +268 -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 +187 -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 +324 -0
- autogen/agentchat/contrib/rag/__init__.py +10 -0
- autogen/agentchat/contrib/rag/chromadb_query_engine.py +272 -0
- autogen/agentchat/contrib/rag/llamaindex_query_engine.py +198 -0
- autogen/agentchat/contrib/rag/mongodb_query_engine.py +329 -0
- autogen/agentchat/contrib/rag/query_engine.py +74 -0
- autogen/agentchat/contrib/retrieve_assistant_agent.py +56 -0
- autogen/agentchat/contrib/retrieve_user_proxy_agent.py +703 -0
- autogen/agentchat/contrib/society_of_mind_agent.py +199 -0
- autogen/agentchat/contrib/swarm_agent.py +1425 -0
- autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
- autogen/agentchat/contrib/vectordb/__init__.py +5 -0
- autogen/agentchat/contrib/vectordb/base.py +232 -0
- autogen/agentchat/contrib/vectordb/chromadb.py +315 -0
- autogen/agentchat/contrib/vectordb/couchbase.py +407 -0
- autogen/agentchat/contrib/vectordb/mongodb.py +550 -0
- autogen/agentchat/contrib/vectordb/pgvectordb.py +928 -0
- autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
- autogen/agentchat/contrib/vectordb/utils.py +126 -0
- autogen/agentchat/contrib/web_surfer.py +303 -0
- autogen/agentchat/conversable_agent.py +4020 -0
- autogen/agentchat/group/__init__.py +64 -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 +41 -0
- autogen/agentchat/group/context_variables.py +192 -0
- autogen/agentchat/group/group_tool_executor.py +202 -0
- autogen/agentchat/group/group_utils.py +591 -0
- autogen/agentchat/group/handoffs.py +244 -0
- autogen/agentchat/group/llm_condition.py +93 -0
- autogen/agentchat/group/multi_agent_chat.py +237 -0
- autogen/agentchat/group/on_condition.py +58 -0
- autogen/agentchat/group/on_context_condition.py +54 -0
- autogen/agentchat/group/patterns/__init__.py +18 -0
- autogen/agentchat/group/patterns/auto.py +159 -0
- autogen/agentchat/group/patterns/manual.py +176 -0
- autogen/agentchat/group/patterns/pattern.py +288 -0
- autogen/agentchat/group/patterns/random.py +106 -0
- autogen/agentchat/group/patterns/round_robin.py +117 -0
- autogen/agentchat/group/reply_result.py +26 -0
- autogen/agentchat/group/speaker_selection_result.py +41 -0
- autogen/agentchat/group/targets/__init__.py +4 -0
- autogen/agentchat/group/targets/group_chat_target.py +132 -0
- autogen/agentchat/group/targets/group_manager_target.py +151 -0
- autogen/agentchat/group/targets/transition_target.py +413 -0
- autogen/agentchat/group/targets/transition_utils.py +6 -0
- autogen/agentchat/groupchat.py +1694 -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 +190 -0
- autogen/agentchat/realtime/experimental/function_observer.py +85 -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 +475 -0
- autogen/agentchat/realtime/experimental/websockets.py +21 -0
- autogen/agentchat/realtime_agent/__init__.py +21 -0
- autogen/agentchat/user_proxy_agent.py +111 -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 +73 -0
- autogen/agents/contrib/time/time_tool_agent.py +51 -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 +316 -0
- autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +118 -0
- autogen/agents/experimental/document_agent/document_agent.py +461 -0
- autogen/agents/experimental/document_agent/document_conditions.py +50 -0
- autogen/agents/experimental/document_agent/document_utils.py +380 -0
- autogen/agents/experimental/document_agent/inmemory_query_engine.py +220 -0
- autogen/agents/experimental/document_agent/parser_utils.py +130 -0
- autogen/agents/experimental/document_agent/url_utils.py +426 -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 +77 -0
- autogen/agents/experimental/websurfer/__init__.py +7 -0
- autogen/agents/experimental/websurfer/websurfer.py +62 -0
- autogen/agents/experimental/wikipedia/__init__.py +7 -0
- autogen/agents/experimental/wikipedia/wikipedia.py +90 -0
- autogen/browser_utils.py +309 -0
- autogen/cache/__init__.py +10 -0
- autogen/cache/abstract_cache_base.py +75 -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 +102 -0
- autogen/cache/in_memory_cache.py +58 -0
- autogen/cache/redis_cache.py +123 -0
- autogen/code_utils.py +596 -0
- autogen/coding/__init__.py +22 -0
- autogen/coding/base.py +119 -0
- autogen/coding/docker_commandline_code_executor.py +268 -0
- autogen/coding/factory.py +47 -0
- autogen/coding/func_with_reqs.py +202 -0
- autogen/coding/jupyter/__init__.py +23 -0
- autogen/coding/jupyter/base.py +36 -0
- autogen/coding/jupyter/docker_jupyter_server.py +167 -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 +231 -0
- autogen/coding/jupyter/jupyter_code_executor.py +160 -0
- autogen/coding/jupyter/local_jupyter_server.py +172 -0
- autogen/coding/local_commandline_code_executor.py +405 -0
- autogen/coding/markdown_code_extractor.py +45 -0
- autogen/coding/utils.py +56 -0
- autogen/doc_utils.py +34 -0
- autogen/events/__init__.py +7 -0
- autogen/events/agent_events.py +1010 -0
- autogen/events/base_event.py +99 -0
- autogen/events/client_events.py +167 -0
- autogen/events/helpers.py +36 -0
- autogen/events/print_event.py +46 -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 +80 -0
- autogen/fast_depends/core/__init__.py +14 -0
- autogen/fast_depends/core/build.py +225 -0
- autogen/fast_depends/core/model.py +576 -0
- autogen/fast_depends/dependencies/__init__.py +15 -0
- autogen/fast_depends/dependencies/model.py +29 -0
- autogen/fast_depends/dependencies/provider.py +39 -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 +280 -0
- autogen/fast_depends/utils.py +187 -0
- autogen/formatting_utils.py +83 -0
- autogen/function_utils.py +13 -0
- autogen/graph_utils.py +178 -0
- autogen/import_utils.py +526 -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 +155 -0
- autogen/interop/langchain/langchain_tool.py +82 -0
- autogen/interop/litellm/__init__.py +7 -0
- autogen/interop/litellm/litellm_config_factory.py +113 -0
- autogen/interop/pydantic_ai/__init__.py +7 -0
- autogen/interop/pydantic_ai/pydantic_ai.py +168 -0
- autogen/interop/registry.py +69 -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 +56 -0
- autogen/io/run_response.py +293 -0
- autogen/io/thread_io_stream.py +63 -0
- autogen/io/websockets.py +213 -0
- autogen/json_utils.py +43 -0
- autogen/llm_config.py +379 -0
- autogen/logger/__init__.py +11 -0
- autogen/logger/base_logger.py +128 -0
- autogen/logger/file_logger.py +261 -0
- autogen/logger/logger_factory.py +42 -0
- autogen/logger/logger_utils.py +57 -0
- autogen/logger/sqlite_logger.py +523 -0
- autogen/math_utils.py +339 -0
- autogen/mcp/__init__.py +7 -0
- autogen/mcp/mcp_client.py +208 -0
- autogen/messages/__init__.py +7 -0
- autogen/messages/agent_messages.py +948 -0
- autogen/messages/base_message.py +107 -0
- autogen/messages/client_messages.py +171 -0
- autogen/messages/print_message.py +49 -0
- autogen/oai/__init__.py +53 -0
- autogen/oai/anthropic.py +714 -0
- autogen/oai/bedrock.py +628 -0
- autogen/oai/cerebras.py +299 -0
- autogen/oai/client.py +1435 -0
- autogen/oai/client_utils.py +169 -0
- autogen/oai/cohere.py +479 -0
- autogen/oai/gemini.py +990 -0
- autogen/oai/gemini_types.py +129 -0
- autogen/oai/groq.py +305 -0
- autogen/oai/mistral.py +303 -0
- autogen/oai/oai_models/__init__.py +11 -0
- autogen/oai/oai_models/_models.py +16 -0
- autogen/oai/oai_models/chat_completion.py +87 -0
- autogen/oai/oai_models/chat_completion_audio.py +32 -0
- autogen/oai/oai_models/chat_completion_message.py +86 -0
- autogen/oai/oai_models/chat_completion_message_tool_call.py +37 -0
- autogen/oai/oai_models/chat_completion_token_logprob.py +63 -0
- autogen/oai/oai_models/completion_usage.py +60 -0
- autogen/oai/ollama.py +643 -0
- autogen/oai/openai_utils.py +881 -0
- autogen/oai/together.py +370 -0
- autogen/retrieve_utils.py +491 -0
- autogen/runtime_logging.py +160 -0
- autogen/token_count_utils.py +267 -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 +41 -0
- autogen/tools/dependency_injection.py +254 -0
- autogen/tools/experimental/__init__.py +43 -0
- autogen/tools/experimental/browser_use/__init__.py +7 -0
- autogen/tools/experimental/browser_use/browser_use.py +161 -0
- autogen/tools/experimental/crawl4ai/__init__.py +7 -0
- autogen/tools/experimental/crawl4ai/crawl4ai.py +153 -0
- autogen/tools/experimental/deep_research/__init__.py +7 -0
- autogen/tools/experimental/deep_research/deep_research.py +328 -0
- autogen/tools/experimental/duckduckgo/__init__.py +7 -0
- autogen/tools/experimental/duckduckgo/duckduckgo_search.py +109 -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 +288 -0
- autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/slack/slack.py +391 -0
- autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/telegram/telegram.py +275 -0
- autogen/tools/experimental/perplexity/__init__.py +7 -0
- autogen/tools/experimental/perplexity/perplexity_search.py +260 -0
- autogen/tools/experimental/tavily/__init__.py +7 -0
- autogen/tools/experimental/tavily/tavily_search.py +183 -0
- autogen/tools/experimental/web_search_preview/__init__.py +7 -0
- autogen/tools/experimental/web_search_preview/web_search_preview.py +114 -0
- autogen/tools/experimental/wikipedia/__init__.py +7 -0
- autogen/tools/experimental/wikipedia/wikipedia.py +287 -0
- autogen/tools/function_utils.py +411 -0
- autogen/tools/tool.py +187 -0
- autogen/tools/toolkit.py +86 -0
- autogen/types.py +29 -0
- autogen/version.py +7 -0
- ag2-0.9.1a1.dist-info/RECORD +0 -6
- ag2-0.9.1a1.dist-info/top_level.txt +0 -1
- {ag2-0.9.1a1.dist-info → ag2-0.9.1.post0.dist-info/licenses}/LICENSE +0 -0
- {ag2-0.9.1a1.dist-info → ag2-0.9.1.post0.dist-info/licenses}/NOTICE.md +0 -0
|
@@ -0,0 +1,287 @@
|
|
|
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 Any, Optional, Union
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
from autogen.import_utils import optional_import_block, require_optional_import
|
|
11
|
+
from autogen.tools import Tool
|
|
12
|
+
|
|
13
|
+
with optional_import_block():
|
|
14
|
+
import wikipediaapi
|
|
15
|
+
|
|
16
|
+
# Maximum allowed length for a query string.
|
|
17
|
+
MAX_QUERY_LENGTH = 300
|
|
18
|
+
# Maximum number of pages to retrieve from a search.
|
|
19
|
+
MAX_PAGE_RETRIEVE = 100
|
|
20
|
+
# Maximum number of characters to return from a Wikipedia page.
|
|
21
|
+
MAX_ARTICLE_LENGTH = 10000
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Document(BaseModel):
|
|
25
|
+
"""Pydantic model representing a Wikipedia document.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
page_content (str): Textual content of the Wikipedia page
|
|
29
|
+
(possibly truncated).
|
|
30
|
+
metadata (dict[str, str]): Additional info, including:
|
|
31
|
+
- source URL
|
|
32
|
+
- title
|
|
33
|
+
- pageid
|
|
34
|
+
- timestamp
|
|
35
|
+
- word count
|
|
36
|
+
- size
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
page_content: str
|
|
40
|
+
metadata: dict[str, str]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class WikipediaClient:
|
|
44
|
+
"""Client for interacting with the Wikipedia API.
|
|
45
|
+
|
|
46
|
+
Supports searching and page retrieval on a specified language edition.
|
|
47
|
+
|
|
48
|
+
Public methods:
|
|
49
|
+
search(query: str, limit: int) -> list[dict[str, Any]]
|
|
50
|
+
get_page(title: str) -> Optional[wikipediaapi.WikipediaPage]
|
|
51
|
+
|
|
52
|
+
Attributes:
|
|
53
|
+
base_url (str): URL of the MediaWiki API endpoint.
|
|
54
|
+
headers (dict[str, str]): HTTP headers, including User-Agent.
|
|
55
|
+
wiki (wikipediaapi.Wikipedia): Low-level Wikipedia API client.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(self, language: str = "en", tool_name: str = "wikipedia-client") -> None:
|
|
59
|
+
"""Initialize the WikipediaClient.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
language (str): ISO code of the Wikipedia edition (e.g., 'en', 'es').
|
|
63
|
+
tool_name (str): Identifier for User-Agent header.
|
|
64
|
+
"""
|
|
65
|
+
self.base_url = f"https://{language}.wikipedia.org/w/api.php"
|
|
66
|
+
self.headers = {"User-Agent": f"autogen.Agent ({tool_name})"}
|
|
67
|
+
self.wiki = wikipediaapi.Wikipedia(
|
|
68
|
+
language=language,
|
|
69
|
+
extract_format=wikipediaapi.ExtractFormat.WIKI,
|
|
70
|
+
user_agent=f"autogen.Agent ({tool_name})",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def search(self, query: str, limit: int = 3) -> Any:
|
|
74
|
+
"""Search Wikipedia for pages matching a query string.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
query (str): The search keywords.
|
|
78
|
+
limit (int): Max number of results to return.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
list[dict[str, Any]]: Each dict has keys:
|
|
82
|
+
- 'title' (str)
|
|
83
|
+
- 'size' (int)
|
|
84
|
+
- 'wordcount' (int)
|
|
85
|
+
- 'timestamp' (str)
|
|
86
|
+
|
|
87
|
+
Raises:
|
|
88
|
+
requests.HTTPError: If the HTTP request to the API fails.
|
|
89
|
+
"""
|
|
90
|
+
params = {
|
|
91
|
+
"action": "query",
|
|
92
|
+
"format": "json",
|
|
93
|
+
"list": "search",
|
|
94
|
+
"srsearch": query,
|
|
95
|
+
"srlimit": str(limit),
|
|
96
|
+
"srprop": "size|wordcount|timestamp",
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
response = requests.get(url=self.base_url, params=params, headers=self.headers)
|
|
100
|
+
response.raise_for_status()
|
|
101
|
+
data = response.json()
|
|
102
|
+
search_data = data.get("query", {}).get("search", [])
|
|
103
|
+
return search_data
|
|
104
|
+
|
|
105
|
+
def get_page(self, title: str) -> Optional[Any]:
|
|
106
|
+
"""Retrieve a WikipediaPage object by title.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
title (str): Title of the Wikipedia page.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
wikipediaapi.WikipediaPage | None: The page object if it exists,
|
|
113
|
+
otherwise None.
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
wikipediaapi.WikipediaException: On lower‑level API errors.
|
|
117
|
+
"""
|
|
118
|
+
page = self.wiki.page(title)
|
|
119
|
+
if not page.exists():
|
|
120
|
+
return None
|
|
121
|
+
return page
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@require_optional_import(["wikipediaapi"], "wikipedia")
|
|
125
|
+
class WikipediaQueryRunTool(Tool):
|
|
126
|
+
"""Tool for querying Wikipedia and returning summarized page results.
|
|
127
|
+
|
|
128
|
+
This tool uses the `wikipediaapi` package to perform searches
|
|
129
|
+
against a specified language edition of Wikipedia and returns
|
|
130
|
+
up to `top_k` page summaries.
|
|
131
|
+
|
|
132
|
+
Public methods:
|
|
133
|
+
query_run(query: str) -> list[str] | str
|
|
134
|
+
|
|
135
|
+
Attributes:
|
|
136
|
+
language (str): Language code for the Wikipedia edition (e.g., 'en', 'es').
|
|
137
|
+
top_k (int): Max number of page summaries returned (≤ MAX_PAGE_RETRIEVE).
|
|
138
|
+
verbose (bool): If True, enables debug logging to stdout.
|
|
139
|
+
wiki_cli (WikipediaClient): Internal client for Wikipedia API calls.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
def __init__(self, language: str = "en", top_k: int = 3, verbose: bool = False) -> None:
|
|
143
|
+
"""Initialize the WikipediaQueryRunTool.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
language (str): ISO code of the Wikipedia edition to query.
|
|
147
|
+
top_k (int): Desired number of summaries (capped by MAX_PAGE_RETRIEVE).
|
|
148
|
+
verbose (bool): If True, print debug information during searches.
|
|
149
|
+
"""
|
|
150
|
+
self.language = language
|
|
151
|
+
self.tool_name = "wikipedia-query-run"
|
|
152
|
+
self.wiki_cli = WikipediaClient(language, self.tool_name)
|
|
153
|
+
self.top_k = min(top_k, MAX_PAGE_RETRIEVE)
|
|
154
|
+
self.verbose = verbose
|
|
155
|
+
super().__init__(
|
|
156
|
+
name=self.tool_name,
|
|
157
|
+
description="Run a Wikipedia query and return page summaries.",
|
|
158
|
+
func_or_tool=self.query_run,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def query_run(self, query: str) -> Union[list[str], str]:
|
|
162
|
+
"""Search Wikipedia and return formatted page summaries.
|
|
163
|
+
|
|
164
|
+
Truncates `query` to MAX_QUERY_LENGTH before searching.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
query (str): Search term(s) to look up in Wikipedia.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
list[str]: Each element is "Page: <title>\nSummary: <text>".
|
|
171
|
+
str: Error message if no results are found or on exception.
|
|
172
|
+
|
|
173
|
+
Note:
|
|
174
|
+
Automatically handles API exceptions and returns error strings for robust operation
|
|
175
|
+
"""
|
|
176
|
+
try:
|
|
177
|
+
if self.verbose:
|
|
178
|
+
print(f"INFO\t [{self.tool_name}] search query='{query[:MAX_QUERY_LENGTH]}' top_k={self.top_k}")
|
|
179
|
+
search_results = self.wiki_cli.search(query[:MAX_QUERY_LENGTH], limit=self.top_k)
|
|
180
|
+
summaries: list[str] = []
|
|
181
|
+
for item in search_results:
|
|
182
|
+
title = item["title"]
|
|
183
|
+
page = self.wiki_cli.get_page(title)
|
|
184
|
+
# Only format the summary if the page exists and has a summary.
|
|
185
|
+
if page is not None and page.summary:
|
|
186
|
+
summary = f"Page: {title}\nSummary: {page.summary}"
|
|
187
|
+
summaries.append(summary)
|
|
188
|
+
if not summaries:
|
|
189
|
+
return "No good Wikipedia Search Result was found"
|
|
190
|
+
return summaries
|
|
191
|
+
except Exception as e:
|
|
192
|
+
return f"wikipedia search failed: {str(e)}"
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@require_optional_import(["wikipediaapi"], "wikipedia")
|
|
196
|
+
class WikipediaPageLoadTool(Tool):
|
|
197
|
+
"""
|
|
198
|
+
A tool to load up to N characters of Wikipedia page content along with metadata.
|
|
199
|
+
|
|
200
|
+
This tool uses a language-specific Wikipedia client to search for relevant articles
|
|
201
|
+
and returns a list of Document objects containing truncated page content and metadata
|
|
202
|
+
(source URL, title, page ID, timestamp, word count, and size). Ideal for agents
|
|
203
|
+
requiring structured Wikipedia data for research, summarization, or contextual enrichment.
|
|
204
|
+
|
|
205
|
+
Attributes:
|
|
206
|
+
language (str): Wikipedia language code (default: "en").
|
|
207
|
+
top_k (int): Maximum number of pages to retrieve per query (default: 3).
|
|
208
|
+
truncate (int): Maximum number of characters of content per page (default: 4000).
|
|
209
|
+
verbose (bool): If True, prints debug information (default: False).
|
|
210
|
+
tool_name (str): Identifier used in User-Agent header.
|
|
211
|
+
wiki_cli (WikipediaClient): Client for interacting with the Wikipedia API.
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
def __init__(self, language: str = "en", top_k: int = 3, truncate: int = 4000, verbose: bool = False) -> None:
|
|
215
|
+
"""
|
|
216
|
+
Initializes the WikipediaPageLoadTool with configurable language, result count, and content length.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
language (str): The language code for the Wikipedia edition (default is "en").
|
|
220
|
+
top_k (int): The maximum number of pages to retrieve per query (default is 3;
|
|
221
|
+
capped at MAX_PAGE_RETRIEVE).
|
|
222
|
+
truncate (int): The maximum number of characters to extract from each page (default is 4000;
|
|
223
|
+
capped at MAX_ARTICLE_LENGTH).
|
|
224
|
+
verbose (bool): If True, enables verbose/debug logging (default is False).
|
|
225
|
+
"""
|
|
226
|
+
self.language = language
|
|
227
|
+
self.top_k = min(top_k, MAX_PAGE_RETRIEVE)
|
|
228
|
+
self.truncate = min(truncate, MAX_ARTICLE_LENGTH)
|
|
229
|
+
self.verbose = verbose
|
|
230
|
+
self.tool_name = "wikipedia-page-load"
|
|
231
|
+
self.wiki_cli = WikipediaClient(language, self.tool_name)
|
|
232
|
+
super().__init__(
|
|
233
|
+
name=self.tool_name,
|
|
234
|
+
description=(
|
|
235
|
+
"Search Wikipedia for relevant pages using a language-specific client. "
|
|
236
|
+
"Returns a list of documents with truncated content and metadata including title, URL, "
|
|
237
|
+
"page ID, timestamp, word count, and page size. Configure number of results with the 'top_k' parameter "
|
|
238
|
+
"and content length with 'truncate'. Useful for research, summarization, or contextual enrichment."
|
|
239
|
+
),
|
|
240
|
+
func_or_tool=self.content_search,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
def content_search(self, query: str) -> Union[list[Document], str]:
|
|
244
|
+
"""
|
|
245
|
+
Executes a Wikipedia search and returns page content plus metadata.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
query (str): The search term to query Wikipedia.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Union[list[Document], str]:
|
|
252
|
+
- list[Document]: Documents with up to `truncate` characters of page text
|
|
253
|
+
and metadata if pages are found.
|
|
254
|
+
- str: Error message if the search fails or no pages are found.
|
|
255
|
+
|
|
256
|
+
Notes:
|
|
257
|
+
- Errors are caught internally and returned as strings.
|
|
258
|
+
- If no matching pages have text content, returns
|
|
259
|
+
"No good Wikipedia Search Result was found".
|
|
260
|
+
"""
|
|
261
|
+
try:
|
|
262
|
+
if self.verbose:
|
|
263
|
+
print(f"INFO\t [{self.tool_name}] search query='{query[:MAX_QUERY_LENGTH]}' top_k={self.top_k}")
|
|
264
|
+
search_results = self.wiki_cli.search(query[:MAX_QUERY_LENGTH], limit=self.top_k)
|
|
265
|
+
docs: list[Document] = []
|
|
266
|
+
for item in search_results:
|
|
267
|
+
page = self.wiki_cli.get_page(item["title"])
|
|
268
|
+
# Only process pages that exist and have text content.
|
|
269
|
+
if page is not None and page.text:
|
|
270
|
+
document = Document(
|
|
271
|
+
page_content=page.text[: self.truncate],
|
|
272
|
+
metadata={
|
|
273
|
+
"source": f"https://{self.language}.wikipedia.org/?curid={item['pageid']}",
|
|
274
|
+
"title": item["title"],
|
|
275
|
+
"pageid": str(item["pageid"]),
|
|
276
|
+
"timestamp": str(item["timestamp"]),
|
|
277
|
+
"wordcount": str(item["wordcount"]),
|
|
278
|
+
"size": str(item["size"]),
|
|
279
|
+
},
|
|
280
|
+
)
|
|
281
|
+
docs.append(document)
|
|
282
|
+
if not docs:
|
|
283
|
+
return "No good Wikipedia Search Result was found"
|
|
284
|
+
return docs
|
|
285
|
+
|
|
286
|
+
except Exception as e:
|
|
287
|
+
return f"wikipedia search failed: {str(e)}"
|
|
@@ -0,0 +1,411 @@
|
|
|
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
|
+
# Portions derived from https://github.com/microsoft/autogen are under the MIT License.
|
|
6
|
+
# SPDX-License-Identifier: MIT
|
|
7
|
+
import functools
|
|
8
|
+
import inspect
|
|
9
|
+
import json
|
|
10
|
+
from logging import getLogger
|
|
11
|
+
from typing import Annotated, Any, Callable, ForwardRef, Optional, TypeVar, Union
|
|
12
|
+
|
|
13
|
+
from packaging.version import parse
|
|
14
|
+
from pydantic import BaseModel, Field, TypeAdapter
|
|
15
|
+
from pydantic import __version__ as pydantic_version
|
|
16
|
+
from pydantic.json_schema import JsonSchemaValue
|
|
17
|
+
from typing_extensions import Literal, get_args, get_origin
|
|
18
|
+
|
|
19
|
+
from ..doc_utils import export_module
|
|
20
|
+
from .dependency_injection import Field as AG2Field
|
|
21
|
+
|
|
22
|
+
if parse(pydantic_version) < parse("2.10.2"):
|
|
23
|
+
from pydantic._internal._typing_extra import eval_type_lenient as try_eval_type
|
|
24
|
+
else:
|
|
25
|
+
from pydantic._internal._typing_extra import try_eval_type
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
__all__ = ["get_function_schema", "load_basemodels_if_needed", "serialize_to_str"]
|
|
29
|
+
|
|
30
|
+
logger = getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
T = TypeVar("T")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any:
|
|
36
|
+
"""Get the type annotation of a parameter.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
annotation: The annotation of the parameter
|
|
40
|
+
globalns: The global namespace of the function
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
The type annotation of the parameter
|
|
44
|
+
"""
|
|
45
|
+
if isinstance(annotation, AG2Field):
|
|
46
|
+
annotation = annotation.description
|
|
47
|
+
if isinstance(annotation, str):
|
|
48
|
+
annotation = ForwardRef(annotation)
|
|
49
|
+
annotation, _ = try_eval_type(annotation, globalns, globalns)
|
|
50
|
+
return annotation
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
|
|
54
|
+
"""Get the signature of a function with type annotations.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
call: The function to get the signature for
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
The signature of the function with type annotations
|
|
61
|
+
"""
|
|
62
|
+
signature = inspect.signature(call)
|
|
63
|
+
globalns = getattr(call, "__globals__", {})
|
|
64
|
+
typed_params = [
|
|
65
|
+
inspect.Parameter(
|
|
66
|
+
name=param.name,
|
|
67
|
+
kind=param.kind,
|
|
68
|
+
default=param.default,
|
|
69
|
+
annotation=get_typed_annotation(param.annotation, globalns),
|
|
70
|
+
)
|
|
71
|
+
for param in signature.parameters.values()
|
|
72
|
+
]
|
|
73
|
+
typed_signature = inspect.Signature(typed_params)
|
|
74
|
+
return typed_signature
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_typed_return_annotation(call: Callable[..., Any]) -> Any:
|
|
78
|
+
"""Get the return annotation of a function.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
call: The function to get the return annotation for
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
The return annotation of the function
|
|
85
|
+
"""
|
|
86
|
+
signature = inspect.signature(call)
|
|
87
|
+
annotation = signature.return_annotation
|
|
88
|
+
|
|
89
|
+
if annotation is inspect.Signature.empty:
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
globalns = getattr(call, "__globals__", {})
|
|
93
|
+
return get_typed_annotation(annotation, globalns)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_param_annotations(typed_signature: inspect.Signature) -> dict[str, Union[Annotated[type[Any], str], type[Any]]]:
|
|
97
|
+
"""Get the type annotations of the parameters of a function
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
typed_signature: The signature of the function with type annotations
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
A dictionary of the type annotations of the parameters of the function
|
|
104
|
+
"""
|
|
105
|
+
return {
|
|
106
|
+
k: v.annotation for k, v in typed_signature.parameters.items() if v.annotation is not inspect.Signature.empty
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class Parameters(BaseModel):
|
|
111
|
+
"""Parameters of a function as defined by the OpenAI API"""
|
|
112
|
+
|
|
113
|
+
type: Literal["object"] = "object"
|
|
114
|
+
properties: dict[str, JsonSchemaValue]
|
|
115
|
+
required: list[str]
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class Function(BaseModel):
|
|
119
|
+
"""A function as defined by the OpenAI API"""
|
|
120
|
+
|
|
121
|
+
description: Annotated[str, Field(description="Description of the function")]
|
|
122
|
+
name: Annotated[str, Field(description="Name of the function")]
|
|
123
|
+
parameters: Annotated[Parameters, Field(description="Parameters of the function")]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class ToolFunction(BaseModel):
|
|
127
|
+
"""A function under tool as defined by the OpenAI API."""
|
|
128
|
+
|
|
129
|
+
type: Literal["function"] = "function"
|
|
130
|
+
function: Annotated[Function, Field(description="Function under tool")]
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def get_parameter_json_schema(k: str, v: Any, default_values: dict[str, Any]) -> JsonSchemaValue:
|
|
134
|
+
"""Get a JSON schema for a parameter as defined by the OpenAI API
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
k: The name of the parameter
|
|
138
|
+
v: The type of the parameter
|
|
139
|
+
default_values: The default values of the parameters of the function
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
A Pydanitc model for the parameter
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def type2description(k: str, v: Union[Annotated[type[Any], str], type[Any]]) -> str:
|
|
146
|
+
if not hasattr(v, "__metadata__"):
|
|
147
|
+
return k
|
|
148
|
+
|
|
149
|
+
# handles Annotated
|
|
150
|
+
retval = v.__metadata__[0]
|
|
151
|
+
if isinstance(retval, AG2Field):
|
|
152
|
+
return retval.description # type: ignore[return-value]
|
|
153
|
+
else:
|
|
154
|
+
raise ValueError(f"Invalid {retval} for parameter {k}, should be a DescriptionField, got {type(retval)}")
|
|
155
|
+
|
|
156
|
+
schema = TypeAdapter(v).json_schema()
|
|
157
|
+
if k in default_values:
|
|
158
|
+
dv = default_values[k]
|
|
159
|
+
schema["default"] = dv
|
|
160
|
+
|
|
161
|
+
schema["description"] = type2description(k, v)
|
|
162
|
+
|
|
163
|
+
return schema
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def get_required_params(typed_signature: inspect.Signature) -> list[str]:
|
|
167
|
+
"""Get the required parameters of a function
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
typed_signature: The signature of the function as returned by inspect.signature
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
A list of the required parameters of the function
|
|
174
|
+
"""
|
|
175
|
+
return [k for k, v in typed_signature.parameters.items() if v.default == inspect.Signature.empty]
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def get_default_values(typed_signature: inspect.Signature) -> dict[str, Any]:
|
|
179
|
+
"""Get default values of parameters of a function
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
typed_signature: The signature of the function as returned by inspect.signature
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
A dictionary of the default values of the parameters of the function
|
|
186
|
+
"""
|
|
187
|
+
return {k: v.default for k, v in typed_signature.parameters.items() if v.default != inspect.Signature.empty}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def get_parameters(
|
|
191
|
+
required: list[str],
|
|
192
|
+
param_annotations: dict[str, Union[Annotated[type[Any], str], type[Any]]],
|
|
193
|
+
default_values: dict[str, Any],
|
|
194
|
+
) -> Parameters:
|
|
195
|
+
"""Get the parameters of a function as defined by the OpenAI API
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
required: The required parameters of the function
|
|
199
|
+
param_annotations: The type annotations of the parameters of the function
|
|
200
|
+
default_values: The default values of the parameters of the function
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
A Pydantic model for the parameters of the function
|
|
204
|
+
"""
|
|
205
|
+
return Parameters(
|
|
206
|
+
properties={
|
|
207
|
+
k: get_parameter_json_schema(k, v, default_values)
|
|
208
|
+
for k, v in param_annotations.items()
|
|
209
|
+
if v is not inspect.Signature.empty
|
|
210
|
+
},
|
|
211
|
+
required=required,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_missing_annotations(typed_signature: inspect.Signature, required: list[str]) -> tuple[set[str], set[str]]:
|
|
216
|
+
"""Get the missing annotations of a function
|
|
217
|
+
|
|
218
|
+
Ignores the parameters with default values as they are not required to be annotated, but logs a warning.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
typed_signature: The signature of the function with type annotations
|
|
222
|
+
required: The required parameters of the function
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
A set of the missing annotations of the function
|
|
226
|
+
"""
|
|
227
|
+
all_missing = {k for k, v in typed_signature.parameters.items() if v.annotation is inspect.Signature.empty}
|
|
228
|
+
missing = all_missing.intersection(set(required))
|
|
229
|
+
unannotated_with_default = all_missing.difference(missing)
|
|
230
|
+
return missing, unannotated_with_default
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@export_module("autogen.tools")
|
|
234
|
+
def get_function_schema(f: Callable[..., Any], *, name: Optional[str] = None, description: str) -> dict[str, Any]:
|
|
235
|
+
"""Get a JSON schema for a function as defined by the OpenAI API
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
f: The function to get the JSON schema for
|
|
239
|
+
name: The name of the function
|
|
240
|
+
description: The description of the function
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
A JSON schema for the function
|
|
244
|
+
|
|
245
|
+
Raises:
|
|
246
|
+
TypeError: If the function is not annotated
|
|
247
|
+
|
|
248
|
+
Examples:
|
|
249
|
+
```python
|
|
250
|
+
def f(a: Annotated[str, "Parameter a"], b: int = 2, c: Annotated[float, "Parameter c"] = 0.1) -> None:
|
|
251
|
+
pass
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
get_function_schema(f, description="function f")
|
|
255
|
+
|
|
256
|
+
# {'type': 'function',
|
|
257
|
+
# 'function': {'description': 'function f',
|
|
258
|
+
# 'name': 'f',
|
|
259
|
+
# 'parameters': {'type': 'object',
|
|
260
|
+
# 'properties': {'a': {'type': 'str', 'description': 'Parameter a'},
|
|
261
|
+
# 'b': {'type': 'int', 'description': 'b'},
|
|
262
|
+
# 'c': {'type': 'float', 'description': 'Parameter c'}},
|
|
263
|
+
# 'required': ['a']}}}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
"""
|
|
267
|
+
typed_signature = get_typed_signature(f)
|
|
268
|
+
required = get_required_params(typed_signature)
|
|
269
|
+
default_values = get_default_values(typed_signature)
|
|
270
|
+
param_annotations = get_param_annotations(typed_signature)
|
|
271
|
+
return_annotation = get_typed_return_annotation(f)
|
|
272
|
+
missing, unannotated_with_default = get_missing_annotations(typed_signature, required)
|
|
273
|
+
|
|
274
|
+
if return_annotation is None:
|
|
275
|
+
logger.warning(
|
|
276
|
+
f"The return type of the function '{f.__name__}' is not annotated. Although annotating it is "
|
|
277
|
+
+ "optional, the function should return either a string, a subclass of 'pydantic.BaseModel'."
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
if unannotated_with_default != set():
|
|
281
|
+
unannotated_with_default_s = [f"'{k}'" for k in sorted(unannotated_with_default)]
|
|
282
|
+
logger.warning(
|
|
283
|
+
f"The following parameters of the function '{f.__name__}' with default values are not annotated: "
|
|
284
|
+
+ f"{', '.join(unannotated_with_default_s)}."
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
if missing != set():
|
|
288
|
+
missing_s = [f"'{k}'" for k in sorted(missing)]
|
|
289
|
+
raise TypeError(
|
|
290
|
+
f"All parameters of the function '{f.__name__}' without default values must be annotated. "
|
|
291
|
+
+ f"The annotations are missing for the following parameters: {', '.join(missing_s)}"
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
fname = name if name else f.__name__
|
|
295
|
+
|
|
296
|
+
parameters = get_parameters(required, param_annotations, default_values=default_values)
|
|
297
|
+
|
|
298
|
+
function = ToolFunction(
|
|
299
|
+
function=Function(
|
|
300
|
+
description=description,
|
|
301
|
+
name=fname,
|
|
302
|
+
parameters=parameters,
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
return function.model_dump()
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def get_load_param_if_needed_function(t: Any) -> Optional[Callable[[dict[str, Any], type[BaseModel]], BaseModel]]:
|
|
310
|
+
"""Get a function to load a parameter if it is a Pydantic model
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
t: The type annotation of the parameter
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
A function to load the parameter if it is a Pydantic model, otherwise None
|
|
317
|
+
|
|
318
|
+
"""
|
|
319
|
+
origin = get_origin(t)
|
|
320
|
+
|
|
321
|
+
if origin is Annotated:
|
|
322
|
+
args = get_args(t)
|
|
323
|
+
if args:
|
|
324
|
+
return get_load_param_if_needed_function(args[0])
|
|
325
|
+
else:
|
|
326
|
+
# Invalid Annotated usage
|
|
327
|
+
return None
|
|
328
|
+
|
|
329
|
+
# Handle generic types (list[str], dict[str,Any], Union[...], etc.) or where t is not a type at all
|
|
330
|
+
# This means it's not a BaseModel subclass
|
|
331
|
+
if origin is not None or not isinstance(t, type):
|
|
332
|
+
return None
|
|
333
|
+
|
|
334
|
+
def load_base_model(v: dict[str, Any], model_type: type[BaseModel]) -> BaseModel:
|
|
335
|
+
return model_type(**v)
|
|
336
|
+
|
|
337
|
+
# Check if it's a class and a subclass of BaseModel
|
|
338
|
+
if issubclass(t, BaseModel):
|
|
339
|
+
return load_base_model
|
|
340
|
+
else:
|
|
341
|
+
return None
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@export_module("autogen.tools")
|
|
345
|
+
def load_basemodels_if_needed(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
346
|
+
"""A decorator to load the parameters of a function if they are Pydantic models
|
|
347
|
+
|
|
348
|
+
Args:
|
|
349
|
+
func: The function with annotated parameters
|
|
350
|
+
|
|
351
|
+
Returns:
|
|
352
|
+
A function that loads the parameters before calling the original function
|
|
353
|
+
|
|
354
|
+
"""
|
|
355
|
+
# get the type annotations of the parameters
|
|
356
|
+
typed_signature = get_typed_signature(func)
|
|
357
|
+
param_annotations = get_param_annotations(typed_signature)
|
|
358
|
+
|
|
359
|
+
# get functions for loading BaseModels when needed based on the type annotations
|
|
360
|
+
kwargs_mapping_with_nones = {k: get_load_param_if_needed_function(t) for k, t in param_annotations.items()}
|
|
361
|
+
|
|
362
|
+
# remove the None values
|
|
363
|
+
kwargs_mapping = {k: f for k, f in kwargs_mapping_with_nones.items() if f is not None}
|
|
364
|
+
|
|
365
|
+
# a function that loads the parameters before calling the original function
|
|
366
|
+
@functools.wraps(func)
|
|
367
|
+
def _load_parameters_if_needed(*args: Any, **kwargs: Any) -> Any:
|
|
368
|
+
# load the BaseModels if needed
|
|
369
|
+
for k, f in kwargs_mapping.items():
|
|
370
|
+
kwargs[k] = f(kwargs[k], param_annotations[k])
|
|
371
|
+
|
|
372
|
+
# call the original function
|
|
373
|
+
return func(*args, **kwargs)
|
|
374
|
+
|
|
375
|
+
@functools.wraps(func)
|
|
376
|
+
async def _a_load_parameters_if_needed(*args: Any, **kwargs: Any) -> Any:
|
|
377
|
+
# load the BaseModels if needed
|
|
378
|
+
for k, f in kwargs_mapping.items():
|
|
379
|
+
kwargs[k] = f(kwargs[k], param_annotations[k])
|
|
380
|
+
|
|
381
|
+
# call the original function
|
|
382
|
+
return await func(*args, **kwargs)
|
|
383
|
+
|
|
384
|
+
if inspect.iscoroutinefunction(func):
|
|
385
|
+
return _a_load_parameters_if_needed
|
|
386
|
+
else:
|
|
387
|
+
return _load_parameters_if_needed
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
class _SerializableResult(BaseModel):
|
|
391
|
+
result: Any
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
@export_module("autogen.tools")
|
|
395
|
+
def serialize_to_str(x: Any) -> str:
|
|
396
|
+
if isinstance(x, str):
|
|
397
|
+
return x
|
|
398
|
+
if isinstance(x, BaseModel):
|
|
399
|
+
return x.model_dump_json()
|
|
400
|
+
|
|
401
|
+
retval_model = _SerializableResult(result=x)
|
|
402
|
+
try:
|
|
403
|
+
return str(retval_model.model_dump()["result"])
|
|
404
|
+
except Exception:
|
|
405
|
+
pass
|
|
406
|
+
|
|
407
|
+
# try json.dumps() and then just return str(x) if that fails too
|
|
408
|
+
try:
|
|
409
|
+
return json.dumps(x, ensure_ascii=False)
|
|
410
|
+
except Exception:
|
|
411
|
+
return str(x)
|