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.
Files changed (423) hide show
  1. ag2-0.10.2.dist-info/METADATA +819 -0
  2. ag2-0.10.2.dist-info/RECORD +423 -0
  3. ag2-0.10.2.dist-info/WHEEL +4 -0
  4. ag2-0.10.2.dist-info/licenses/LICENSE +201 -0
  5. ag2-0.10.2.dist-info/licenses/NOTICE.md +19 -0
  6. autogen/__init__.py +88 -0
  7. autogen/_website/__init__.py +3 -0
  8. autogen/_website/generate_api_references.py +426 -0
  9. autogen/_website/generate_mkdocs.py +1216 -0
  10. autogen/_website/notebook_processor.py +475 -0
  11. autogen/_website/process_notebooks.py +656 -0
  12. autogen/_website/utils.py +413 -0
  13. autogen/a2a/__init__.py +36 -0
  14. autogen/a2a/agent_executor.py +86 -0
  15. autogen/a2a/client.py +357 -0
  16. autogen/a2a/errors.py +18 -0
  17. autogen/a2a/httpx_client_factory.py +79 -0
  18. autogen/a2a/server.py +221 -0
  19. autogen/a2a/utils.py +207 -0
  20. autogen/agentchat/__init__.py +47 -0
  21. autogen/agentchat/agent.py +180 -0
  22. autogen/agentchat/assistant_agent.py +86 -0
  23. autogen/agentchat/chat.py +325 -0
  24. autogen/agentchat/contrib/__init__.py +5 -0
  25. autogen/agentchat/contrib/agent_eval/README.md +7 -0
  26. autogen/agentchat/contrib/agent_eval/agent_eval.py +108 -0
  27. autogen/agentchat/contrib/agent_eval/criterion.py +43 -0
  28. autogen/agentchat/contrib/agent_eval/critic_agent.py +44 -0
  29. autogen/agentchat/contrib/agent_eval/quantifier_agent.py +39 -0
  30. autogen/agentchat/contrib/agent_eval/subcritic_agent.py +45 -0
  31. autogen/agentchat/contrib/agent_eval/task.py +42 -0
  32. autogen/agentchat/contrib/agent_optimizer.py +432 -0
  33. autogen/agentchat/contrib/capabilities/__init__.py +5 -0
  34. autogen/agentchat/contrib/capabilities/agent_capability.py +20 -0
  35. autogen/agentchat/contrib/capabilities/generate_images.py +301 -0
  36. autogen/agentchat/contrib/capabilities/teachability.py +393 -0
  37. autogen/agentchat/contrib/capabilities/text_compressors.py +66 -0
  38. autogen/agentchat/contrib/capabilities/tools_capability.py +22 -0
  39. autogen/agentchat/contrib/capabilities/transform_messages.py +93 -0
  40. autogen/agentchat/contrib/capabilities/transforms.py +578 -0
  41. autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
  42. autogen/agentchat/contrib/capabilities/vision_capability.py +215 -0
  43. autogen/agentchat/contrib/captainagent/__init__.py +9 -0
  44. autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
  45. autogen/agentchat/contrib/captainagent/captainagent.py +514 -0
  46. autogen/agentchat/contrib/captainagent/tool_retriever.py +334 -0
  47. autogen/agentchat/contrib/captainagent/tools/README.md +44 -0
  48. autogen/agentchat/contrib/captainagent/tools/__init__.py +5 -0
  49. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +40 -0
  50. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +28 -0
  51. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +28 -0
  52. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +28 -0
  53. autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +21 -0
  54. autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +30 -0
  55. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +27 -0
  56. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +53 -0
  57. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +53 -0
  58. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +38 -0
  59. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +21 -0
  60. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +34 -0
  61. autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +60 -0
  62. autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +61 -0
  63. autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +47 -0
  64. autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +33 -0
  65. autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +21 -0
  66. autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +35 -0
  67. autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +21 -0
  68. autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +18 -0
  69. autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +28 -0
  70. autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +31 -0
  71. autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +16 -0
  72. autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +25 -0
  73. autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +23 -0
  74. autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +27 -0
  75. autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +28 -0
  76. autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +34 -0
  77. autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +39 -0
  78. autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +23 -0
  79. autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +36 -0
  80. autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +15 -0
  81. autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +15 -0
  82. autogen/agentchat/contrib/captainagent/tools/requirements.txt +10 -0
  83. autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +34 -0
  84. autogen/agentchat/contrib/gpt_assistant_agent.py +526 -0
  85. autogen/agentchat/contrib/graph_rag/__init__.py +9 -0
  86. autogen/agentchat/contrib/graph_rag/document.py +29 -0
  87. autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +167 -0
  88. autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +103 -0
  89. autogen/agentchat/contrib/graph_rag/graph_query_engine.py +53 -0
  90. autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +63 -0
  91. autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +263 -0
  92. autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +83 -0
  93. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +210 -0
  94. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +93 -0
  95. autogen/agentchat/contrib/img_utils.py +397 -0
  96. autogen/agentchat/contrib/llamaindex_conversable_agent.py +117 -0
  97. autogen/agentchat/contrib/llava_agent.py +189 -0
  98. autogen/agentchat/contrib/math_user_proxy_agent.py +464 -0
  99. autogen/agentchat/contrib/multimodal_conversable_agent.py +125 -0
  100. autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +325 -0
  101. autogen/agentchat/contrib/rag/__init__.py +10 -0
  102. autogen/agentchat/contrib/rag/chromadb_query_engine.py +268 -0
  103. autogen/agentchat/contrib/rag/llamaindex_query_engine.py +195 -0
  104. autogen/agentchat/contrib/rag/mongodb_query_engine.py +319 -0
  105. autogen/agentchat/contrib/rag/query_engine.py +76 -0
  106. autogen/agentchat/contrib/retrieve_assistant_agent.py +59 -0
  107. autogen/agentchat/contrib/retrieve_user_proxy_agent.py +704 -0
  108. autogen/agentchat/contrib/society_of_mind_agent.py +200 -0
  109. autogen/agentchat/contrib/swarm_agent.py +1404 -0
  110. autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
  111. autogen/agentchat/contrib/vectordb/__init__.py +5 -0
  112. autogen/agentchat/contrib/vectordb/base.py +224 -0
  113. autogen/agentchat/contrib/vectordb/chromadb.py +316 -0
  114. autogen/agentchat/contrib/vectordb/couchbase.py +405 -0
  115. autogen/agentchat/contrib/vectordb/mongodb.py +551 -0
  116. autogen/agentchat/contrib/vectordb/pgvectordb.py +927 -0
  117. autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
  118. autogen/agentchat/contrib/vectordb/utils.py +126 -0
  119. autogen/agentchat/contrib/web_surfer.py +304 -0
  120. autogen/agentchat/conversable_agent.py +4307 -0
  121. autogen/agentchat/group/__init__.py +67 -0
  122. autogen/agentchat/group/available_condition.py +91 -0
  123. autogen/agentchat/group/context_condition.py +77 -0
  124. autogen/agentchat/group/context_expression.py +238 -0
  125. autogen/agentchat/group/context_str.py +39 -0
  126. autogen/agentchat/group/context_variables.py +182 -0
  127. autogen/agentchat/group/events/transition_events.py +111 -0
  128. autogen/agentchat/group/group_tool_executor.py +324 -0
  129. autogen/agentchat/group/group_utils.py +659 -0
  130. autogen/agentchat/group/guardrails.py +179 -0
  131. autogen/agentchat/group/handoffs.py +303 -0
  132. autogen/agentchat/group/llm_condition.py +93 -0
  133. autogen/agentchat/group/multi_agent_chat.py +291 -0
  134. autogen/agentchat/group/on_condition.py +55 -0
  135. autogen/agentchat/group/on_context_condition.py +51 -0
  136. autogen/agentchat/group/patterns/__init__.py +18 -0
  137. autogen/agentchat/group/patterns/auto.py +160 -0
  138. autogen/agentchat/group/patterns/manual.py +177 -0
  139. autogen/agentchat/group/patterns/pattern.py +295 -0
  140. autogen/agentchat/group/patterns/random.py +106 -0
  141. autogen/agentchat/group/patterns/round_robin.py +117 -0
  142. autogen/agentchat/group/reply_result.py +24 -0
  143. autogen/agentchat/group/safeguards/__init__.py +21 -0
  144. autogen/agentchat/group/safeguards/api.py +241 -0
  145. autogen/agentchat/group/safeguards/enforcer.py +1158 -0
  146. autogen/agentchat/group/safeguards/events.py +140 -0
  147. autogen/agentchat/group/safeguards/validator.py +435 -0
  148. autogen/agentchat/group/speaker_selection_result.py +41 -0
  149. autogen/agentchat/group/targets/__init__.py +4 -0
  150. autogen/agentchat/group/targets/function_target.py +245 -0
  151. autogen/agentchat/group/targets/group_chat_target.py +133 -0
  152. autogen/agentchat/group/targets/group_manager_target.py +151 -0
  153. autogen/agentchat/group/targets/transition_target.py +424 -0
  154. autogen/agentchat/group/targets/transition_utils.py +6 -0
  155. autogen/agentchat/groupchat.py +1832 -0
  156. autogen/agentchat/realtime/__init__.py +3 -0
  157. autogen/agentchat/realtime/experimental/__init__.py +20 -0
  158. autogen/agentchat/realtime/experimental/audio_adapters/__init__.py +8 -0
  159. autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +148 -0
  160. autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +139 -0
  161. autogen/agentchat/realtime/experimental/audio_observer.py +42 -0
  162. autogen/agentchat/realtime/experimental/clients/__init__.py +15 -0
  163. autogen/agentchat/realtime/experimental/clients/gemini/__init__.py +7 -0
  164. autogen/agentchat/realtime/experimental/clients/gemini/client.py +274 -0
  165. autogen/agentchat/realtime/experimental/clients/oai/__init__.py +8 -0
  166. autogen/agentchat/realtime/experimental/clients/oai/base_client.py +220 -0
  167. autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +243 -0
  168. autogen/agentchat/realtime/experimental/clients/oai/utils.py +48 -0
  169. autogen/agentchat/realtime/experimental/clients/realtime_client.py +191 -0
  170. autogen/agentchat/realtime/experimental/function_observer.py +84 -0
  171. autogen/agentchat/realtime/experimental/realtime_agent.py +158 -0
  172. autogen/agentchat/realtime/experimental/realtime_events.py +42 -0
  173. autogen/agentchat/realtime/experimental/realtime_observer.py +100 -0
  174. autogen/agentchat/realtime/experimental/realtime_swarm.py +533 -0
  175. autogen/agentchat/realtime/experimental/websockets.py +21 -0
  176. autogen/agentchat/realtime_agent/__init__.py +21 -0
  177. autogen/agentchat/user_proxy_agent.py +114 -0
  178. autogen/agentchat/utils.py +206 -0
  179. autogen/agents/__init__.py +3 -0
  180. autogen/agents/contrib/__init__.py +10 -0
  181. autogen/agents/contrib/time/__init__.py +8 -0
  182. autogen/agents/contrib/time/time_reply_agent.py +74 -0
  183. autogen/agents/contrib/time/time_tool_agent.py +52 -0
  184. autogen/agents/experimental/__init__.py +27 -0
  185. autogen/agents/experimental/deep_research/__init__.py +7 -0
  186. autogen/agents/experimental/deep_research/deep_research.py +52 -0
  187. autogen/agents/experimental/discord/__init__.py +7 -0
  188. autogen/agents/experimental/discord/discord.py +66 -0
  189. autogen/agents/experimental/document_agent/__init__.py +19 -0
  190. autogen/agents/experimental/document_agent/chroma_query_engine.py +301 -0
  191. autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +113 -0
  192. autogen/agents/experimental/document_agent/document_agent.py +643 -0
  193. autogen/agents/experimental/document_agent/document_conditions.py +50 -0
  194. autogen/agents/experimental/document_agent/document_utils.py +376 -0
  195. autogen/agents/experimental/document_agent/inmemory_query_engine.py +214 -0
  196. autogen/agents/experimental/document_agent/parser_utils.py +134 -0
  197. autogen/agents/experimental/document_agent/url_utils.py +417 -0
  198. autogen/agents/experimental/reasoning/__init__.py +7 -0
  199. autogen/agents/experimental/reasoning/reasoning_agent.py +1178 -0
  200. autogen/agents/experimental/slack/__init__.py +7 -0
  201. autogen/agents/experimental/slack/slack.py +73 -0
  202. autogen/agents/experimental/telegram/__init__.py +7 -0
  203. autogen/agents/experimental/telegram/telegram.py +76 -0
  204. autogen/agents/experimental/websurfer/__init__.py +7 -0
  205. autogen/agents/experimental/websurfer/websurfer.py +70 -0
  206. autogen/agents/experimental/wikipedia/__init__.py +7 -0
  207. autogen/agents/experimental/wikipedia/wikipedia.py +88 -0
  208. autogen/browser_utils.py +309 -0
  209. autogen/cache/__init__.py +10 -0
  210. autogen/cache/abstract_cache_base.py +71 -0
  211. autogen/cache/cache.py +203 -0
  212. autogen/cache/cache_factory.py +88 -0
  213. autogen/cache/cosmos_db_cache.py +144 -0
  214. autogen/cache/disk_cache.py +97 -0
  215. autogen/cache/in_memory_cache.py +54 -0
  216. autogen/cache/redis_cache.py +119 -0
  217. autogen/code_utils.py +598 -0
  218. autogen/coding/__init__.py +30 -0
  219. autogen/coding/base.py +120 -0
  220. autogen/coding/docker_commandline_code_executor.py +283 -0
  221. autogen/coding/factory.py +56 -0
  222. autogen/coding/func_with_reqs.py +203 -0
  223. autogen/coding/jupyter/__init__.py +23 -0
  224. autogen/coding/jupyter/base.py +36 -0
  225. autogen/coding/jupyter/docker_jupyter_server.py +160 -0
  226. autogen/coding/jupyter/embedded_ipython_code_executor.py +182 -0
  227. autogen/coding/jupyter/import_utils.py +82 -0
  228. autogen/coding/jupyter/jupyter_client.py +224 -0
  229. autogen/coding/jupyter/jupyter_code_executor.py +154 -0
  230. autogen/coding/jupyter/local_jupyter_server.py +164 -0
  231. autogen/coding/local_commandline_code_executor.py +341 -0
  232. autogen/coding/markdown_code_extractor.py +44 -0
  233. autogen/coding/utils.py +55 -0
  234. autogen/coding/yepcode_code_executor.py +197 -0
  235. autogen/doc_utils.py +35 -0
  236. autogen/environments/__init__.py +10 -0
  237. autogen/environments/docker_python_environment.py +365 -0
  238. autogen/environments/python_environment.py +125 -0
  239. autogen/environments/system_python_environment.py +85 -0
  240. autogen/environments/venv_python_environment.py +220 -0
  241. autogen/environments/working_directory.py +74 -0
  242. autogen/events/__init__.py +7 -0
  243. autogen/events/agent_events.py +1016 -0
  244. autogen/events/base_event.py +100 -0
  245. autogen/events/client_events.py +168 -0
  246. autogen/events/helpers.py +44 -0
  247. autogen/events/print_event.py +45 -0
  248. autogen/exception_utils.py +73 -0
  249. autogen/extensions/__init__.py +5 -0
  250. autogen/fast_depends/__init__.py +16 -0
  251. autogen/fast_depends/_compat.py +75 -0
  252. autogen/fast_depends/core/__init__.py +14 -0
  253. autogen/fast_depends/core/build.py +206 -0
  254. autogen/fast_depends/core/model.py +527 -0
  255. autogen/fast_depends/dependencies/__init__.py +15 -0
  256. autogen/fast_depends/dependencies/model.py +30 -0
  257. autogen/fast_depends/dependencies/provider.py +40 -0
  258. autogen/fast_depends/library/__init__.py +10 -0
  259. autogen/fast_depends/library/model.py +46 -0
  260. autogen/fast_depends/py.typed +6 -0
  261. autogen/fast_depends/schema.py +66 -0
  262. autogen/fast_depends/use.py +272 -0
  263. autogen/fast_depends/utils.py +177 -0
  264. autogen/formatting_utils.py +83 -0
  265. autogen/function_utils.py +13 -0
  266. autogen/graph_utils.py +173 -0
  267. autogen/import_utils.py +539 -0
  268. autogen/interop/__init__.py +22 -0
  269. autogen/interop/crewai/__init__.py +7 -0
  270. autogen/interop/crewai/crewai.py +88 -0
  271. autogen/interop/interoperability.py +71 -0
  272. autogen/interop/interoperable.py +46 -0
  273. autogen/interop/langchain/__init__.py +8 -0
  274. autogen/interop/langchain/langchain_chat_model_factory.py +156 -0
  275. autogen/interop/langchain/langchain_tool.py +78 -0
  276. autogen/interop/litellm/__init__.py +7 -0
  277. autogen/interop/litellm/litellm_config_factory.py +178 -0
  278. autogen/interop/pydantic_ai/__init__.py +7 -0
  279. autogen/interop/pydantic_ai/pydantic_ai.py +172 -0
  280. autogen/interop/registry.py +70 -0
  281. autogen/io/__init__.py +15 -0
  282. autogen/io/base.py +151 -0
  283. autogen/io/console.py +56 -0
  284. autogen/io/processors/__init__.py +12 -0
  285. autogen/io/processors/base.py +21 -0
  286. autogen/io/processors/console_event_processor.py +61 -0
  287. autogen/io/run_response.py +294 -0
  288. autogen/io/thread_io_stream.py +63 -0
  289. autogen/io/websockets.py +214 -0
  290. autogen/json_utils.py +42 -0
  291. autogen/llm_clients/MIGRATION_TO_V2.md +782 -0
  292. autogen/llm_clients/__init__.py +77 -0
  293. autogen/llm_clients/client_v2.py +122 -0
  294. autogen/llm_clients/models/__init__.py +55 -0
  295. autogen/llm_clients/models/content_blocks.py +389 -0
  296. autogen/llm_clients/models/unified_message.py +145 -0
  297. autogen/llm_clients/models/unified_response.py +83 -0
  298. autogen/llm_clients/openai_completions_client.py +444 -0
  299. autogen/llm_config/__init__.py +11 -0
  300. autogen/llm_config/client.py +59 -0
  301. autogen/llm_config/config.py +461 -0
  302. autogen/llm_config/entry.py +169 -0
  303. autogen/llm_config/types.py +37 -0
  304. autogen/llm_config/utils.py +223 -0
  305. autogen/logger/__init__.py +11 -0
  306. autogen/logger/base_logger.py +129 -0
  307. autogen/logger/file_logger.py +262 -0
  308. autogen/logger/logger_factory.py +42 -0
  309. autogen/logger/logger_utils.py +57 -0
  310. autogen/logger/sqlite_logger.py +524 -0
  311. autogen/math_utils.py +338 -0
  312. autogen/mcp/__init__.py +7 -0
  313. autogen/mcp/__main__.py +78 -0
  314. autogen/mcp/helpers.py +45 -0
  315. autogen/mcp/mcp_client.py +349 -0
  316. autogen/mcp/mcp_proxy/__init__.py +19 -0
  317. autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +62 -0
  318. autogen/mcp/mcp_proxy/mcp_proxy.py +577 -0
  319. autogen/mcp/mcp_proxy/operation_grouping.py +166 -0
  320. autogen/mcp/mcp_proxy/operation_renaming.py +110 -0
  321. autogen/mcp/mcp_proxy/patch_fastapi_code_generator.py +98 -0
  322. autogen/mcp/mcp_proxy/security.py +399 -0
  323. autogen/mcp/mcp_proxy/security_schema_visitor.py +37 -0
  324. autogen/messages/__init__.py +7 -0
  325. autogen/messages/agent_messages.py +946 -0
  326. autogen/messages/base_message.py +108 -0
  327. autogen/messages/client_messages.py +172 -0
  328. autogen/messages/print_message.py +48 -0
  329. autogen/oai/__init__.py +61 -0
  330. autogen/oai/anthropic.py +1516 -0
  331. autogen/oai/bedrock.py +800 -0
  332. autogen/oai/cerebras.py +302 -0
  333. autogen/oai/client.py +1658 -0
  334. autogen/oai/client_utils.py +196 -0
  335. autogen/oai/cohere.py +494 -0
  336. autogen/oai/gemini.py +1045 -0
  337. autogen/oai/gemini_types.py +156 -0
  338. autogen/oai/groq.py +319 -0
  339. autogen/oai/mistral.py +311 -0
  340. autogen/oai/oai_models/__init__.py +23 -0
  341. autogen/oai/oai_models/_models.py +16 -0
  342. autogen/oai/oai_models/chat_completion.py +86 -0
  343. autogen/oai/oai_models/chat_completion_audio.py +32 -0
  344. autogen/oai/oai_models/chat_completion_message.py +97 -0
  345. autogen/oai/oai_models/chat_completion_message_tool_call.py +60 -0
  346. autogen/oai/oai_models/chat_completion_token_logprob.py +62 -0
  347. autogen/oai/oai_models/completion_usage.py +59 -0
  348. autogen/oai/ollama.py +657 -0
  349. autogen/oai/openai_responses.py +451 -0
  350. autogen/oai/openai_utils.py +897 -0
  351. autogen/oai/together.py +387 -0
  352. autogen/remote/__init__.py +18 -0
  353. autogen/remote/agent.py +199 -0
  354. autogen/remote/agent_service.py +197 -0
  355. autogen/remote/errors.py +17 -0
  356. autogen/remote/httpx_client_factory.py +131 -0
  357. autogen/remote/protocol.py +37 -0
  358. autogen/remote/retry.py +102 -0
  359. autogen/remote/runtime.py +96 -0
  360. autogen/retrieve_utils.py +490 -0
  361. autogen/runtime_logging.py +161 -0
  362. autogen/testing/__init__.py +12 -0
  363. autogen/testing/messages.py +45 -0
  364. autogen/testing/test_agent.py +111 -0
  365. autogen/token_count_utils.py +280 -0
  366. autogen/tools/__init__.py +20 -0
  367. autogen/tools/contrib/__init__.py +9 -0
  368. autogen/tools/contrib/time/__init__.py +7 -0
  369. autogen/tools/contrib/time/time.py +40 -0
  370. autogen/tools/dependency_injection.py +249 -0
  371. autogen/tools/experimental/__init__.py +54 -0
  372. autogen/tools/experimental/browser_use/__init__.py +7 -0
  373. autogen/tools/experimental/browser_use/browser_use.py +154 -0
  374. autogen/tools/experimental/code_execution/__init__.py +7 -0
  375. autogen/tools/experimental/code_execution/python_code_execution.py +86 -0
  376. autogen/tools/experimental/crawl4ai/__init__.py +7 -0
  377. autogen/tools/experimental/crawl4ai/crawl4ai.py +150 -0
  378. autogen/tools/experimental/deep_research/__init__.py +7 -0
  379. autogen/tools/experimental/deep_research/deep_research.py +329 -0
  380. autogen/tools/experimental/duckduckgo/__init__.py +7 -0
  381. autogen/tools/experimental/duckduckgo/duckduckgo_search.py +103 -0
  382. autogen/tools/experimental/firecrawl/__init__.py +7 -0
  383. autogen/tools/experimental/firecrawl/firecrawl_tool.py +836 -0
  384. autogen/tools/experimental/google/__init__.py +14 -0
  385. autogen/tools/experimental/google/authentication/__init__.py +11 -0
  386. autogen/tools/experimental/google/authentication/credentials_hosted_provider.py +43 -0
  387. autogen/tools/experimental/google/authentication/credentials_local_provider.py +91 -0
  388. autogen/tools/experimental/google/authentication/credentials_provider.py +35 -0
  389. autogen/tools/experimental/google/drive/__init__.py +9 -0
  390. autogen/tools/experimental/google/drive/drive_functions.py +124 -0
  391. autogen/tools/experimental/google/drive/toolkit.py +88 -0
  392. autogen/tools/experimental/google/model.py +17 -0
  393. autogen/tools/experimental/google/toolkit_protocol.py +19 -0
  394. autogen/tools/experimental/google_search/__init__.py +8 -0
  395. autogen/tools/experimental/google_search/google_search.py +93 -0
  396. autogen/tools/experimental/google_search/youtube_search.py +181 -0
  397. autogen/tools/experimental/messageplatform/__init__.py +17 -0
  398. autogen/tools/experimental/messageplatform/discord/__init__.py +7 -0
  399. autogen/tools/experimental/messageplatform/discord/discord.py +284 -0
  400. autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
  401. autogen/tools/experimental/messageplatform/slack/slack.py +385 -0
  402. autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
  403. autogen/tools/experimental/messageplatform/telegram/telegram.py +271 -0
  404. autogen/tools/experimental/perplexity/__init__.py +7 -0
  405. autogen/tools/experimental/perplexity/perplexity_search.py +249 -0
  406. autogen/tools/experimental/reliable/__init__.py +10 -0
  407. autogen/tools/experimental/reliable/reliable.py +1311 -0
  408. autogen/tools/experimental/searxng/__init__.py +7 -0
  409. autogen/tools/experimental/searxng/searxng_search.py +142 -0
  410. autogen/tools/experimental/tavily/__init__.py +7 -0
  411. autogen/tools/experimental/tavily/tavily_search.py +176 -0
  412. autogen/tools/experimental/web_search_preview/__init__.py +7 -0
  413. autogen/tools/experimental/web_search_preview/web_search_preview.py +120 -0
  414. autogen/tools/experimental/wikipedia/__init__.py +7 -0
  415. autogen/tools/experimental/wikipedia/wikipedia.py +284 -0
  416. autogen/tools/function_utils.py +412 -0
  417. autogen/tools/tool.py +188 -0
  418. autogen/tools/toolkit.py +86 -0
  419. autogen/types.py +29 -0
  420. autogen/version.py +7 -0
  421. templates/client_template/main.jinja2 +72 -0
  422. templates/config_template/config.jinja2 +7 -0
  423. templates/main.jinja2 +61 -0
@@ -0,0 +1,490 @@
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 glob
8
+ import hashlib
9
+ import logging
10
+ import os
11
+ import re
12
+ from collections.abc import Callable
13
+ from typing import Any
14
+ from urllib.parse import urlparse
15
+
16
+ import requests
17
+
18
+ from .import_utils import optional_import_block, require_optional_import
19
+ from .token_count_utils import count_token
20
+
21
+ with optional_import_block():
22
+ import chromadb
23
+ import markdownify
24
+ from bs4 import BeautifulSoup
25
+
26
+ if chromadb.__version__ < "0.4.15":
27
+ from chromadb.api import API
28
+ else:
29
+ from chromadb.api import ClientAPI as API # noqa: N814
30
+ import chromadb.utils.embedding_functions as ef
31
+ import pypdf
32
+ from chromadb.api.types import QueryResult
33
+
34
+
35
+ with optional_import_block() as result:
36
+ from unstructured.partition.auto import partition
37
+
38
+ HAS_UNSTRUCTURED = result.is_successful
39
+
40
+ logger = logging.getLogger(__name__)
41
+ TEXT_FORMATS = [
42
+ "txt",
43
+ "json",
44
+ "csv",
45
+ "tsv",
46
+ "md",
47
+ "html",
48
+ "htm",
49
+ "rtf",
50
+ "rst",
51
+ "jsonl",
52
+ "log",
53
+ "xml",
54
+ "yaml",
55
+ "yml",
56
+ "pdf",
57
+ "mdx",
58
+ ]
59
+ UNSTRUCTURED_FORMATS = [
60
+ "doc",
61
+ "docx",
62
+ "epub",
63
+ "msg",
64
+ "odt",
65
+ "org",
66
+ "pdf",
67
+ "ppt",
68
+ "pptx",
69
+ "rtf",
70
+ "rst",
71
+ "xlsx",
72
+ ] # These formats will be parsed by the 'unstructured' library, if installed.
73
+ if HAS_UNSTRUCTURED:
74
+ TEXT_FORMATS += UNSTRUCTURED_FORMATS
75
+ TEXT_FORMATS = list(set(TEXT_FORMATS))
76
+ VALID_CHUNK_MODES = frozenset({"one_line", "multi_lines"})
77
+ RAG_MINIMUM_MESSAGE_LENGTH = int(os.environ.get("RAG_MINIMUM_MESSAGE_LENGTH", 5))
78
+
79
+
80
+ def split_text_to_chunks(
81
+ text: str,
82
+ max_tokens: int = 4000,
83
+ chunk_mode: str = "multi_lines",
84
+ must_break_at_empty_line: bool = True,
85
+ overlap: int = 0, # number of overlapping lines
86
+ ):
87
+ """Split a long text into chunks of max_tokens."""
88
+ if chunk_mode not in VALID_CHUNK_MODES:
89
+ raise AssertionError
90
+ if chunk_mode == "one_line":
91
+ must_break_at_empty_line = False
92
+ overlap = 0
93
+ chunks = []
94
+ lines = text.split("\n")
95
+ num_lines = len(lines)
96
+ if num_lines < 3 and must_break_at_empty_line:
97
+ logger.warning("The input text has less than 3 lines. Set `must_break_at_empty_line` to `False`")
98
+ must_break_at_empty_line = False
99
+ lines_tokens = [count_token(line) for line in lines]
100
+ sum_tokens = sum(lines_tokens)
101
+ while sum_tokens > max_tokens:
102
+ estimated_line_cut = 2 if chunk_mode == "one_line" else max(int(max_tokens / sum_tokens * len(lines)), 2)
103
+ cnt = 0
104
+ prev = ""
105
+ for cnt in reversed(range(estimated_line_cut)):
106
+ if must_break_at_empty_line and lines[cnt].strip() != "":
107
+ continue
108
+ if sum(lines_tokens[:cnt]) <= max_tokens:
109
+ prev = "\n".join(lines[:cnt])
110
+ break
111
+ if cnt == 0:
112
+ logger.warning(
113
+ f"max_tokens is too small to fit a single line of text. Breaking this line:\n\t{lines[0][:100]} ..."
114
+ )
115
+ if not must_break_at_empty_line:
116
+ split_len = max(
117
+ int(max_tokens / (lines_tokens[0] * 0.9 * len(lines[0]) + 0.1)), RAG_MINIMUM_MESSAGE_LENGTH
118
+ )
119
+ prev = lines[0][:split_len]
120
+ lines[0] = lines[0][split_len:]
121
+ lines_tokens[0] = count_token(lines[0])
122
+ else:
123
+ logger.warning("Failed to split docs with must_break_at_empty_line being True, set to False.")
124
+ must_break_at_empty_line = False
125
+ (
126
+ chunks.append(prev) if len(prev) >= RAG_MINIMUM_MESSAGE_LENGTH else None
127
+ ) # don't add chunks less than RAG_MINIMUM_MESSAGE_LENGTH characters
128
+ lines = lines[cnt - overlap if cnt > overlap else cnt :]
129
+ lines_tokens = lines_tokens[cnt - overlap if cnt > overlap else cnt :]
130
+ sum_tokens = sum(lines_tokens)
131
+ text_to_chunk = "\n".join(lines).strip()
132
+ (
133
+ chunks.append(text_to_chunk) if len(text_to_chunk) >= RAG_MINIMUM_MESSAGE_LENGTH else None
134
+ ) # don't add chunks less than RAG_MINIMUM_MESSAGE_LENGTH characters
135
+ return chunks
136
+
137
+
138
+ @require_optional_import("pypdf", "retrievechat")
139
+ def extract_text_from_pdf(file: str) -> str:
140
+ """Extract text from PDF files"""
141
+ text = ""
142
+ with open(file, "rb") as f:
143
+ reader = pypdf.PdfReader(f)
144
+ if reader.is_encrypted: # Check if the PDF is encrypted
145
+ try:
146
+ reader.decrypt("")
147
+ except pypdf.errors.FileNotDecryptedError as e:
148
+ logger.warning(f"Could not decrypt PDF {file}, {e}")
149
+ return text # Return empty text if PDF could not be decrypted
150
+
151
+ for page_num in range(len(reader.pages)):
152
+ page = reader.pages[page_num]
153
+ text += page.extract_text()
154
+
155
+ if not text.strip(): # Debugging line to check if text is empty
156
+ logger.warning(f"Could not decrypt PDF {file}")
157
+
158
+ return text
159
+
160
+
161
+ def split_files_to_chunks(
162
+ files: list[tuple[str, str] | str],
163
+ max_tokens: int = 4000,
164
+ chunk_mode: str = "multi_lines",
165
+ must_break_at_empty_line: bool = True,
166
+ custom_text_split_function: Callable[[str], list[str]] | None = None,
167
+ ) -> tuple[list[str], list[dict[str, Any]]]:
168
+ """Split a list of files into chunks of max_tokens."""
169
+ chunks = []
170
+ sources = []
171
+
172
+ for file in files:
173
+ if isinstance(file, tuple):
174
+ url = file[1]
175
+ file = file[0]
176
+ else:
177
+ url = None
178
+ _, file_extension = os.path.splitext(file)
179
+ file_extension = file_extension.lower()
180
+
181
+ if HAS_UNSTRUCTURED and file_extension[1:] in UNSTRUCTURED_FORMATS:
182
+ text = partition(file)
183
+ text = "\n".join([t.text for t in text]) if len(text) > 0 else ""
184
+ elif file_extension == ".pdf":
185
+ text = extract_text_from_pdf(file)
186
+ else: # For non-PDF text-based files
187
+ with open(file, encoding="utf-8", errors="ignore") as f:
188
+ text = f.read()
189
+
190
+ if not text.strip(): # Debugging line to check if text is empty after reading
191
+ logger.warning(f"No text available in file: {file}")
192
+ continue # Skip to the next file if no text is available
193
+
194
+ if custom_text_split_function is not None:
195
+ tmp_chunks = custom_text_split_function(text)
196
+ else:
197
+ tmp_chunks = split_text_to_chunks(text, max_tokens, chunk_mode, must_break_at_empty_line)
198
+ chunks += tmp_chunks
199
+ sources += [{"source": url if url else file}] * len(tmp_chunks)
200
+
201
+ return chunks, sources
202
+
203
+
204
+ def get_files_from_dir(dir_path: str | list[str], types: list[str] = TEXT_FORMATS, recursive: bool = True) -> list[Any]:
205
+ """Return a list of all the files in a given directory, a url, a file path or a list of them."""
206
+ if len(types) == 0:
207
+ raise ValueError("types cannot be empty.")
208
+ types = [t[1:].lower() if t.startswith(".") else t.lower() for t in set(types)]
209
+ types += [t.upper() for t in types]
210
+
211
+ files = []
212
+ # If the path is a list of files or urls, process and return them
213
+ if isinstance(dir_path, list):
214
+ for item in dir_path:
215
+ if os.path.isfile(item):
216
+ files.append(item)
217
+ elif is_url(item):
218
+ filepath = get_file_from_url(item)
219
+ if filepath:
220
+ files.append(filepath)
221
+ elif os.path.exists(item):
222
+ try:
223
+ files.extend(get_files_from_dir(item, types, recursive))
224
+ except ValueError:
225
+ logger.warning(f"Directory {item} does not exist. Skipping.")
226
+ else:
227
+ logger.warning(f"File {item} does not exist. Skipping.")
228
+ return files
229
+
230
+ # If the path is a file, return it
231
+ if os.path.isfile(dir_path):
232
+ return [dir_path]
233
+
234
+ # If the path is a url, download it and return the downloaded file
235
+ if is_url(dir_path):
236
+ filepath = get_file_from_url(dir_path)
237
+ if filepath:
238
+ return [filepath]
239
+ else:
240
+ return []
241
+
242
+ if os.path.exists(dir_path):
243
+ for type in types:
244
+ if recursive:
245
+ files += glob.glob(os.path.join(dir_path, f"**/*.{type}"), recursive=True)
246
+ else:
247
+ files += glob.glob(os.path.join(dir_path, f"*.{type}"), recursive=False)
248
+ else:
249
+ logger.error(f"Directory {dir_path} does not exist.")
250
+ raise ValueError(f"Directory {dir_path} does not exist.")
251
+ return files
252
+
253
+
254
+ @require_optional_import(["markdownify", "bs4"], "retrievechat")
255
+ def parse_html_to_markdown(html: str, url: str = None) -> str:
256
+ """Parse HTML to markdown."""
257
+ soup = BeautifulSoup(html, "html.parser")
258
+ title = soup.title.string
259
+ # Remove javascript and style blocks
260
+ for script in soup(["script", "style"]):
261
+ script.extract()
262
+
263
+ # Convert to markdown -- Wikipedia gets special attention to get a clean version of the page
264
+ if isinstance(url, str) and url.startswith("https://en.wikipedia.org/"):
265
+ body_elm = soup.find("div", {"id": "mw-content-text"})
266
+ title_elm = soup.find("span", {"class": "mw-page-title-main"})
267
+
268
+ if body_elm:
269
+ # What's the title
270
+ main_title = soup.title.string
271
+ if title_elm and len(title_elm) > 0:
272
+ main_title = title_elm.string
273
+ webpage_text = "# " + main_title + "\n\n" + markdownify.MarkdownConverter().convert_soup(body_elm)
274
+ else:
275
+ webpage_text = markdownify.MarkdownConverter().convert_soup(soup)
276
+ else:
277
+ webpage_text = markdownify.MarkdownConverter().convert_soup(soup)
278
+
279
+ # Convert newlines
280
+ webpage_text = re.sub(r"\r\n", "\n", webpage_text)
281
+ webpage_text = re.sub(r"\n{2,}", "\n\n", webpage_text).strip()
282
+ webpage_text = "# " + title + "\n\n" + webpage_text
283
+ return webpage_text
284
+
285
+
286
+ def _generate_file_name_from_url(url: str, max_length=255) -> str:
287
+ url_bytes = url.encode("utf-8")
288
+ hash = hashlib.blake2b(url_bytes).hexdigest()
289
+ parsed_url = urlparse(url)
290
+ file_name = os.path.basename(url)
291
+ file_name = (
292
+ f"{parsed_url.netloc}_{file_name}_{hash[: min(8, max_length - len(parsed_url.netloc) - len(file_name) - 1)]}"
293
+ )
294
+ return file_name
295
+
296
+
297
+ def get_file_from_url(url: str, save_path: str = None) -> tuple[str, str]:
298
+ """Download a file from a URL."""
299
+ if save_path is None:
300
+ save_path = "tmp/chromadb"
301
+ os.makedirs(save_path, exist_ok=True)
302
+ if os.path.isdir(save_path):
303
+ filename = _generate_file_name_from_url(url)
304
+ save_path = os.path.join(save_path, filename)
305
+ else:
306
+ os.makedirs(os.path.dirname(save_path), exist_ok=True)
307
+
308
+ custom_headers = {
309
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
310
+ }
311
+ try:
312
+ response = requests.get(url, stream=True, headers=custom_headers, timeout=30)
313
+ response.raise_for_status()
314
+ except requests.exceptions.RequestException as e:
315
+ logger.warning(f"Failed to download {url}, {e}")
316
+ return None
317
+
318
+ content_type = response.headers.get("content-type", "")
319
+ if "text/html" in content_type:
320
+ # Get the content of the response
321
+ html = ""
322
+ for chunk in response.iter_content(chunk_size=8192, decode_unicode=True):
323
+ html += chunk
324
+ text = parse_html_to_markdown(html, url)
325
+ with open(save_path, "w", encoding="utf-8") as f:
326
+ f.write(text)
327
+ else:
328
+ with open(save_path, "wb") as f:
329
+ for chunk in response.iter_content(chunk_size=8192):
330
+ f.write(chunk)
331
+ return save_path, url
332
+
333
+
334
+ def is_url(string: str):
335
+ """Return True if the string is a valid URL."""
336
+ try:
337
+ result = urlparse(string)
338
+ return all([result.scheme, result.netloc])
339
+ except ValueError:
340
+ return False
341
+
342
+
343
+ @require_optional_import("chromadb", "retrievechat")
344
+ def create_vector_db_from_dir(
345
+ dir_path: str | list[str],
346
+ max_tokens: int = 4000,
347
+ client: "API" = None,
348
+ db_path: str = "tmp/chromadb.db",
349
+ collection_name: str = "all-my-documents",
350
+ get_or_create: bool = False,
351
+ chunk_mode: str = "multi_lines",
352
+ must_break_at_empty_line: bool = True,
353
+ embedding_model: str = "all-MiniLM-L6-v2",
354
+ embedding_function: Callable = None,
355
+ custom_text_split_function: Callable = None,
356
+ custom_text_types: list[str] = TEXT_FORMATS,
357
+ recursive: bool = True,
358
+ extra_docs: bool = False,
359
+ ) -> "API":
360
+ """Create a vector db from all the files in a given directory, the directory can also be a single file or a url to
361
+ a single file. We support chromadb compatible APIs to create the vector db, this function is not required if
362
+ you prepared your own vector db.
363
+
364
+ Args:
365
+ dir_path (Union[str, List[str]]): the path to the directory, file, url or a list of them.
366
+ max_tokens (Optional, int): the maximum number of tokens per chunk. Default is 4000.
367
+ client (Optional, API): the chromadb client. Default is None.
368
+ db_path (Optional, str): the path to the chromadb. Default is "tmp/chromadb.db". The default was `/tmp/chromadb.db` for version `<=0.2.24`.
369
+ collection_name (Optional, str): the name of the collection. Default is "all-my-documents".
370
+ get_or_create (Optional, bool): Whether to get or create the collection. Default is False. If True, the collection
371
+ will be returned if it already exists. Will raise ValueError if the collection already exists and get_or_create is False.
372
+ chunk_mode (Optional, str): the chunk mode. Default is "multi_lines".
373
+ must_break_at_empty_line (Optional, bool): Whether to break at empty line. Default is True.
374
+ embedding_model (Optional, str): the embedding model to use. Default is "all-MiniLM-L6-v2". Will be ignored if
375
+ embedding_function is not None.
376
+ embedding_function (Optional, Callable): the embedding function to use. Default is None, SentenceTransformer with
377
+ the given `embedding_model` will be used. If you want to use OpenAI, Cohere, HuggingFace or other embedding
378
+ functions, you can pass it here, follow the examples in `https://docs.trychroma.com/embeddings`.
379
+ custom_text_split_function (Optional, Callable): a custom function to split a string into a list of strings.
380
+ Default is None, will use the default function in `autogen.retrieve_utils.split_text_to_chunks`.
381
+ custom_text_types (Optional, List[str]): a list of file types to be processed. Default is TEXT_FORMATS.
382
+ recursive (Optional, bool): whether to search documents recursively in the dir_path. Default is True.
383
+ extra_docs (Optional, bool): whether to add more documents in the collection. Default is False
384
+
385
+ Returns:
386
+ The chromadb client.
387
+ """
388
+ if client is None:
389
+ client = chromadb.PersistentClient(path=db_path)
390
+ try:
391
+ embedding_function = (
392
+ ef.SentenceTransformerEmbeddingFunction(embedding_model)
393
+ if embedding_function is None
394
+ else embedding_function
395
+ )
396
+ collection = client.create_collection(
397
+ collection_name,
398
+ get_or_create=get_or_create,
399
+ embedding_function=embedding_function,
400
+ # https://github.com/nmslib/hnswlib#supported-distances
401
+ # https://github.com/chroma-core/chroma/blob/566bc80f6c8ee29f7d99b6322654f32183c368c4/chromadb/segment/impl/vector/local_hnsw.py#L184
402
+ # https://github.com/nmslib/hnswlib/blob/master/ALGO_PARAMS.md
403
+ metadata={"hnsw:space": "ip", "hnsw:construction_ef": 30, "hnsw:M": 32}, # ip, l2, cosine
404
+ )
405
+
406
+ length = 0
407
+ if extra_docs:
408
+ length = len(collection.get()["ids"])
409
+
410
+ if custom_text_split_function is not None:
411
+ chunks, sources = split_files_to_chunks(
412
+ get_files_from_dir(dir_path, custom_text_types, recursive),
413
+ custom_text_split_function=custom_text_split_function,
414
+ )
415
+ else:
416
+ chunks, sources = split_files_to_chunks(
417
+ get_files_from_dir(dir_path, custom_text_types, recursive),
418
+ max_tokens,
419
+ chunk_mode,
420
+ must_break_at_empty_line,
421
+ )
422
+ logger.info(f"Found {len(chunks)} chunks.")
423
+ # Upsert in batch of 40000 or less if the total number of chunks is less than 40000
424
+ for i in range(0, len(chunks), min(40000, len(chunks))):
425
+ end_idx = i + min(40000, len(chunks) - i)
426
+ collection.upsert(
427
+ documents=chunks[i:end_idx],
428
+ ids=[f"doc_{j + length}" for j in range(i, end_idx)], # unique for each doc
429
+ metadatas=sources[i:end_idx],
430
+ )
431
+ except ValueError as e:
432
+ logger.warning(f"{e}")
433
+ return client
434
+
435
+
436
+ @require_optional_import("chromadb", "retrievechat")
437
+ def query_vector_db(
438
+ query_texts: list[str],
439
+ n_results: int = 10,
440
+ client: "API" = None,
441
+ db_path: str = "tmp/chromadb.db",
442
+ collection_name: str = "all-my-documents",
443
+ search_string: str = "",
444
+ embedding_model: str = "all-MiniLM-L6-v2",
445
+ embedding_function: Callable = None,
446
+ ) -> "QueryResult":
447
+ """Query a vector db. We support chromadb compatible APIs, it's not required if you prepared your own vector db
448
+ and query function.
449
+
450
+ Args:
451
+ query_texts (List[str]): the list of strings which will be used to query the vector db.
452
+ n_results (Optional, int): the number of results to return. Default is 10.
453
+ client (Optional, API): the chromadb compatible client. Default is None, a chromadb client will be used.
454
+ db_path (Optional, str): the path to the vector db. Default is "tmp/chromadb.db". The default was `/tmp/chromadb.db` for version `<=0.2.24`.
455
+ collection_name (Optional, str): the name of the collection. Default is "all-my-documents".
456
+ search_string (Optional, str): the search string. Only docs that contain an exact match of this string will be retrieved. Default is "".
457
+ embedding_model (Optional, str): the embedding model to use. Default is "all-MiniLM-L6-v2". Will be ignored if
458
+ embedding_function is not None.
459
+ embedding_function (Optional, Callable): the embedding function to use. Default is None, SentenceTransformer with
460
+ the given `embedding_model` will be used. If you want to use OpenAI, Cohere, HuggingFace or other embedding
461
+ functions, you can pass it here, follow the examples in `https://docs.trychroma.com/embeddings`.
462
+
463
+ Returns:
464
+ The query result. The format is:
465
+
466
+ ```python
467
+ class QueryResult(TypedDict):
468
+ ids: List[IDs]
469
+ embeddings: Optional[List[List[Embedding]]]
470
+ documents: Optional[List[List[Document]]]
471
+ metadatas: Optional[List[List[Metadata]]]
472
+ distances: Optional[List[List[float]]]
473
+ ```
474
+ """
475
+ if client is None:
476
+ client = chromadb.PersistentClient(path=db_path)
477
+ # the collection's embedding function is always the default one, but we want to use the one we used to create the
478
+ # collection. So we compute the embeddings ourselves and pass it to the query function.
479
+ collection = client.get_collection(collection_name)
480
+ embedding_function = (
481
+ ef.SentenceTransformerEmbeddingFunction(embedding_model) if embedding_function is None else embedding_function
482
+ )
483
+ query_embeddings = embedding_function(query_texts)
484
+ # Query/search n most similar results. You can also .get by id
485
+ results = collection.query(
486
+ query_embeddings=query_embeddings,
487
+ n_results=n_results,
488
+ where_document={"$contains": search_string} if search_string else None, # optional filter
489
+ )
490
+ return results
@@ -0,0 +1,161 @@
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
+ from __future__ import annotations
8
+
9
+ import logging
10
+ import sqlite3
11
+ import uuid
12
+ from collections.abc import Callable
13
+ from typing import TYPE_CHECKING, Any, Literal, TypeVar
14
+
15
+ from .logger.base_logger import BaseLogger, LLMConfig
16
+ from .logger.logger_factory import LoggerFactory
17
+
18
+ if TYPE_CHECKING:
19
+ from openai import AzureOpenAI, OpenAI
20
+ from openai.types.chat import ChatCompletion
21
+
22
+ from . import Agent, ConversableAgent, OpenAIWrapper
23
+ from .oai.anthropic import AnthropicClient
24
+ from .oai.bedrock import BedrockClient
25
+ from .oai.cerebras import CerebrasClient
26
+ from .oai.cohere import CohereClient
27
+ from .oai.gemini import GeminiClient
28
+ from .oai.groq import GroqClient
29
+ from .oai.mistral import MistralAIClient
30
+ from .oai.ollama import OllamaClient
31
+ from .oai.together import TogetherClient
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+ autogen_logger = None
36
+ is_logging = False
37
+
38
+ F = TypeVar("F", bound=Callable[..., Any])
39
+
40
+
41
+ def start(
42
+ logger: BaseLogger | None = None,
43
+ logger_type: Literal["sqlite", "file"] = "sqlite",
44
+ config: dict[str, Any] | None = None,
45
+ ) -> str:
46
+ """Start logging for the runtime.
47
+
48
+ Args:
49
+ logger (BaseLogger): A logger instance
50
+ logger_type (str): The type of logger to use (default: sqlite)
51
+ config (dict): Configuration for the logger
52
+ Returns:
53
+ session_id (str(uuid.uuid4)): a unique id for the logging session
54
+ """
55
+ global autogen_logger
56
+ global is_logging
57
+
58
+ autogen_logger = logger or LoggerFactory.get_logger(logger_type=logger_type, config=config)
59
+
60
+ try:
61
+ session_id = autogen_logger.start()
62
+ is_logging = True
63
+ except Exception as e:
64
+ logger.error(f"[runtime logging] Failed to start logging: {e}")
65
+ finally:
66
+ return session_id
67
+
68
+
69
+ def log_chat_completion(
70
+ invocation_id: uuid.UUID,
71
+ client_id: int,
72
+ wrapper_id: int,
73
+ agent: str | Agent,
74
+ request: dict[str, float | str | list[dict[str, str]]],
75
+ response: str | ChatCompletion,
76
+ is_cached: int,
77
+ cost: float,
78
+ start_time: str,
79
+ ) -> None:
80
+ if autogen_logger is None:
81
+ logger.error("[runtime logging] log_chat_completion: autogen logger is None")
82
+ return
83
+
84
+ autogen_logger.log_chat_completion(
85
+ invocation_id, client_id, wrapper_id, agent, request, response, is_cached, cost, start_time
86
+ )
87
+
88
+
89
+ def log_new_agent(agent: ConversableAgent, init_args: dict[str, Any]) -> None:
90
+ if autogen_logger is None:
91
+ logger.error("[runtime logging] log_new_agent: autogen logger is None")
92
+ return
93
+
94
+ autogen_logger.log_new_agent(agent, init_args)
95
+
96
+
97
+ def log_event(source: str | Agent, name: str, **kwargs: dict[str, Any]) -> None:
98
+ if autogen_logger is None:
99
+ logger.error("[runtime logging] log_event: autogen logger is None")
100
+ return
101
+
102
+ autogen_logger.log_event(source, name, **kwargs)
103
+
104
+
105
+ def log_function_use(agent: str | Agent, function: F, args: dict[str, Any], returns: any):
106
+ if autogen_logger is None:
107
+ logger.error("[runtime logging] log_function_use: autogen logger is None")
108
+ return
109
+
110
+ autogen_logger.log_function_use(agent, function, args, returns)
111
+
112
+
113
+ def log_new_wrapper(wrapper: OpenAIWrapper, init_args: dict[str, LLMConfig | list[LLMConfig]]) -> None:
114
+ if autogen_logger is None:
115
+ logger.error("[runtime logging] log_new_wrapper: autogen logger is None")
116
+ return
117
+
118
+ autogen_logger.log_new_wrapper(wrapper, init_args)
119
+
120
+
121
+ def log_new_client(
122
+ client: (
123
+ AzureOpenAI
124
+ | OpenAI
125
+ | CerebrasClient
126
+ | GeminiClient
127
+ | AnthropicClient
128
+ | MistralAIClient
129
+ | TogetherClient
130
+ | GroqClient
131
+ | CohereClient
132
+ | OllamaClient
133
+ | BedrockClient
134
+ ),
135
+ wrapper: OpenAIWrapper,
136
+ init_args: dict[str, Any],
137
+ ) -> None:
138
+ if autogen_logger is None:
139
+ logger.error("[runtime logging] log_new_client: autogen logger is None")
140
+ return
141
+
142
+ autogen_logger.log_new_client(client, wrapper, init_args)
143
+
144
+
145
+ def stop() -> None:
146
+ global is_logging
147
+ if autogen_logger:
148
+ autogen_logger.stop()
149
+ is_logging = False
150
+
151
+
152
+ def get_connection() -> None | sqlite3.Connection:
153
+ if autogen_logger is None:
154
+ logger.error("[runtime logging] get_connection: autogen logger is None")
155
+ return None
156
+
157
+ return autogen_logger.get_connection()
158
+
159
+
160
+ def logging_enabled() -> bool:
161
+ return is_logging
@@ -0,0 +1,12 @@
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 .messages import ToolCall, tools_message
6
+ from .test_agent import TestAgent
7
+
8
+ __all__ = (
9
+ "TestAgent",
10
+ "ToolCall",
11
+ "tools_message",
12
+ )