ag2 0.9.7__py3-none-any.whl → 0.9.8.post1__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.

Files changed (236) hide show
  1. {ag2-0.9.7.dist-info → ag2-0.9.8.post1.dist-info}/METADATA +102 -75
  2. ag2-0.9.8.post1.dist-info/RECORD +387 -0
  3. autogen/__init__.py +1 -2
  4. autogen/_website/generate_api_references.py +4 -5
  5. autogen/_website/generate_mkdocs.py +9 -15
  6. autogen/_website/notebook_processor.py +13 -14
  7. autogen/_website/process_notebooks.py +10 -10
  8. autogen/_website/utils.py +5 -4
  9. autogen/agentchat/agent.py +13 -13
  10. autogen/agentchat/assistant_agent.py +7 -6
  11. autogen/agentchat/contrib/agent_eval/agent_eval.py +3 -3
  12. autogen/agentchat/contrib/agent_eval/critic_agent.py +3 -3
  13. autogen/agentchat/contrib/agent_eval/quantifier_agent.py +3 -3
  14. autogen/agentchat/contrib/agent_eval/subcritic_agent.py +3 -3
  15. autogen/agentchat/contrib/agent_optimizer.py +3 -3
  16. autogen/agentchat/contrib/capabilities/generate_images.py +11 -11
  17. autogen/agentchat/contrib/capabilities/teachability.py +15 -15
  18. autogen/agentchat/contrib/capabilities/transforms.py +17 -18
  19. autogen/agentchat/contrib/capabilities/transforms_util.py +5 -5
  20. autogen/agentchat/contrib/capabilities/vision_capability.py +4 -3
  21. autogen/agentchat/contrib/captainagent/agent_builder.py +30 -30
  22. autogen/agentchat/contrib/captainagent/captainagent.py +22 -21
  23. autogen/agentchat/contrib/captainagent/tool_retriever.py +2 -3
  24. autogen/agentchat/contrib/gpt_assistant_agent.py +9 -9
  25. autogen/agentchat/contrib/graph_rag/document.py +3 -3
  26. autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +3 -3
  27. autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +6 -6
  28. autogen/agentchat/contrib/graph_rag/graph_query_engine.py +3 -3
  29. autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +5 -11
  30. autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +6 -6
  31. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +7 -7
  32. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +6 -6
  33. autogen/agentchat/contrib/img_utils.py +1 -1
  34. autogen/agentchat/contrib/llamaindex_conversable_agent.py +11 -11
  35. autogen/agentchat/contrib/llava_agent.py +18 -4
  36. autogen/agentchat/contrib/math_user_proxy_agent.py +11 -11
  37. autogen/agentchat/contrib/multimodal_conversable_agent.py +8 -8
  38. autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +6 -5
  39. autogen/agentchat/contrib/rag/chromadb_query_engine.py +22 -26
  40. autogen/agentchat/contrib/rag/llamaindex_query_engine.py +14 -17
  41. autogen/agentchat/contrib/rag/mongodb_query_engine.py +27 -37
  42. autogen/agentchat/contrib/rag/query_engine.py +7 -5
  43. autogen/agentchat/contrib/retrieve_assistant_agent.py +5 -5
  44. autogen/agentchat/contrib/retrieve_user_proxy_agent.py +8 -7
  45. autogen/agentchat/contrib/society_of_mind_agent.py +15 -14
  46. autogen/agentchat/contrib/swarm_agent.py +76 -98
  47. autogen/agentchat/contrib/text_analyzer_agent.py +7 -7
  48. autogen/agentchat/contrib/vectordb/base.py +10 -18
  49. autogen/agentchat/contrib/vectordb/chromadb.py +2 -1
  50. autogen/agentchat/contrib/vectordb/couchbase.py +18 -20
  51. autogen/agentchat/contrib/vectordb/mongodb.py +6 -5
  52. autogen/agentchat/contrib/vectordb/pgvectordb.py +40 -41
  53. autogen/agentchat/contrib/vectordb/qdrant.py +5 -5
  54. autogen/agentchat/contrib/web_surfer.py +20 -19
  55. autogen/agentchat/conversable_agent.py +292 -290
  56. autogen/agentchat/group/context_str.py +1 -3
  57. autogen/agentchat/group/context_variables.py +15 -25
  58. autogen/agentchat/group/group_tool_executor.py +10 -10
  59. autogen/agentchat/group/group_utils.py +15 -15
  60. autogen/agentchat/group/guardrails.py +7 -7
  61. autogen/agentchat/group/handoffs.py +19 -36
  62. autogen/agentchat/group/multi_agent_chat.py +7 -7
  63. autogen/agentchat/group/on_condition.py +4 -7
  64. autogen/agentchat/group/on_context_condition.py +4 -7
  65. autogen/agentchat/group/patterns/auto.py +8 -7
  66. autogen/agentchat/group/patterns/manual.py +7 -6
  67. autogen/agentchat/group/patterns/pattern.py +13 -12
  68. autogen/agentchat/group/patterns/random.py +3 -3
  69. autogen/agentchat/group/patterns/round_robin.py +3 -3
  70. autogen/agentchat/group/reply_result.py +2 -4
  71. autogen/agentchat/group/speaker_selection_result.py +5 -5
  72. autogen/agentchat/group/targets/group_chat_target.py +7 -6
  73. autogen/agentchat/group/targets/group_manager_target.py +4 -4
  74. autogen/agentchat/group/targets/transition_target.py +2 -1
  75. autogen/agentchat/groupchat.py +58 -61
  76. autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +4 -4
  77. autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +4 -4
  78. autogen/agentchat/realtime/experimental/clients/gemini/client.py +7 -7
  79. autogen/agentchat/realtime/experimental/clients/oai/base_client.py +8 -8
  80. autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +6 -6
  81. autogen/agentchat/realtime/experimental/clients/realtime_client.py +10 -9
  82. autogen/agentchat/realtime/experimental/realtime_agent.py +10 -9
  83. autogen/agentchat/realtime/experimental/realtime_observer.py +3 -3
  84. autogen/agentchat/realtime/experimental/realtime_swarm.py +44 -44
  85. autogen/agentchat/user_proxy_agent.py +10 -9
  86. autogen/agentchat/utils.py +3 -3
  87. autogen/agents/contrib/time/time_reply_agent.py +6 -5
  88. autogen/agents/contrib/time/time_tool_agent.py +2 -1
  89. autogen/agents/experimental/deep_research/deep_research.py +3 -3
  90. autogen/agents/experimental/discord/discord.py +2 -2
  91. autogen/agents/experimental/document_agent/chroma_query_engine.py +29 -44
  92. autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +9 -14
  93. autogen/agents/experimental/document_agent/document_agent.py +15 -16
  94. autogen/agents/experimental/document_agent/document_conditions.py +3 -3
  95. autogen/agents/experimental/document_agent/document_utils.py +5 -9
  96. autogen/agents/experimental/document_agent/inmemory_query_engine.py +14 -20
  97. autogen/agents/experimental/document_agent/parser_utils.py +4 -4
  98. autogen/agents/experimental/document_agent/url_utils.py +14 -23
  99. autogen/agents/experimental/reasoning/reasoning_agent.py +33 -33
  100. autogen/agents/experimental/slack/slack.py +2 -2
  101. autogen/agents/experimental/telegram/telegram.py +2 -3
  102. autogen/agents/experimental/websurfer/websurfer.py +4 -4
  103. autogen/agents/experimental/wikipedia/wikipedia.py +5 -7
  104. autogen/browser_utils.py +8 -8
  105. autogen/cache/abstract_cache_base.py +5 -5
  106. autogen/cache/cache.py +12 -12
  107. autogen/cache/cache_factory.py +4 -4
  108. autogen/cache/cosmos_db_cache.py +9 -9
  109. autogen/cache/disk_cache.py +6 -6
  110. autogen/cache/in_memory_cache.py +4 -4
  111. autogen/cache/redis_cache.py +4 -4
  112. autogen/code_utils.py +18 -18
  113. autogen/coding/base.py +6 -6
  114. autogen/coding/docker_commandline_code_executor.py +9 -9
  115. autogen/coding/func_with_reqs.py +7 -6
  116. autogen/coding/jupyter/base.py +3 -3
  117. autogen/coding/jupyter/docker_jupyter_server.py +3 -4
  118. autogen/coding/jupyter/import_utils.py +3 -3
  119. autogen/coding/jupyter/jupyter_client.py +5 -5
  120. autogen/coding/jupyter/jupyter_code_executor.py +3 -4
  121. autogen/coding/jupyter/local_jupyter_server.py +2 -6
  122. autogen/coding/local_commandline_code_executor.py +8 -7
  123. autogen/coding/markdown_code_extractor.py +1 -2
  124. autogen/coding/utils.py +1 -2
  125. autogen/doc_utils.py +3 -2
  126. autogen/environments/docker_python_environment.py +19 -29
  127. autogen/environments/python_environment.py +8 -17
  128. autogen/environments/system_python_environment.py +3 -4
  129. autogen/environments/venv_python_environment.py +8 -12
  130. autogen/environments/working_directory.py +1 -2
  131. autogen/events/agent_events.py +106 -109
  132. autogen/events/base_event.py +6 -5
  133. autogen/events/client_events.py +15 -14
  134. autogen/events/helpers.py +1 -1
  135. autogen/events/print_event.py +4 -5
  136. autogen/fast_depends/_compat.py +10 -15
  137. autogen/fast_depends/core/build.py +17 -36
  138. autogen/fast_depends/core/model.py +64 -113
  139. autogen/fast_depends/dependencies/model.py +2 -1
  140. autogen/fast_depends/dependencies/provider.py +3 -2
  141. autogen/fast_depends/library/model.py +4 -4
  142. autogen/fast_depends/schema.py +7 -7
  143. autogen/fast_depends/use.py +17 -25
  144. autogen/fast_depends/utils.py +10 -30
  145. autogen/formatting_utils.py +6 -6
  146. autogen/graph_utils.py +1 -4
  147. autogen/import_utils.py +13 -13
  148. autogen/interop/crewai/crewai.py +2 -2
  149. autogen/interop/interoperable.py +2 -2
  150. autogen/interop/langchain/langchain_chat_model_factory.py +3 -2
  151. autogen/interop/langchain/langchain_tool.py +2 -6
  152. autogen/interop/litellm/litellm_config_factory.py +6 -7
  153. autogen/interop/pydantic_ai/pydantic_ai.py +4 -7
  154. autogen/interop/registry.py +2 -1
  155. autogen/io/base.py +5 -5
  156. autogen/io/run_response.py +33 -32
  157. autogen/io/websockets.py +6 -5
  158. autogen/json_utils.py +1 -2
  159. autogen/llm_config/__init__.py +11 -0
  160. autogen/llm_config/client.py +58 -0
  161. autogen/llm_config/config.py +384 -0
  162. autogen/llm_config/entry.py +154 -0
  163. autogen/logger/base_logger.py +4 -3
  164. autogen/logger/file_logger.py +2 -1
  165. autogen/logger/logger_factory.py +2 -2
  166. autogen/logger/logger_utils.py +2 -2
  167. autogen/logger/sqlite_logger.py +2 -1
  168. autogen/math_utils.py +4 -5
  169. autogen/mcp/__main__.py +6 -6
  170. autogen/mcp/helpers.py +4 -4
  171. autogen/mcp/mcp_client.py +170 -29
  172. autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +3 -4
  173. autogen/mcp/mcp_proxy/mcp_proxy.py +23 -26
  174. autogen/mcp/mcp_proxy/operation_grouping.py +4 -5
  175. autogen/mcp/mcp_proxy/operation_renaming.py +6 -10
  176. autogen/mcp/mcp_proxy/security.py +2 -3
  177. autogen/messages/agent_messages.py +96 -98
  178. autogen/messages/base_message.py +6 -5
  179. autogen/messages/client_messages.py +15 -14
  180. autogen/messages/print_message.py +4 -5
  181. autogen/oai/__init__.py +1 -2
  182. autogen/oai/anthropic.py +42 -41
  183. autogen/oai/bedrock.py +68 -57
  184. autogen/oai/cerebras.py +26 -25
  185. autogen/oai/client.py +113 -139
  186. autogen/oai/client_utils.py +3 -3
  187. autogen/oai/cohere.py +34 -11
  188. autogen/oai/gemini.py +39 -17
  189. autogen/oai/gemini_types.py +11 -12
  190. autogen/oai/groq.py +22 -10
  191. autogen/oai/mistral.py +17 -11
  192. autogen/oai/oai_models/__init__.py +14 -2
  193. autogen/oai/oai_models/_models.py +2 -2
  194. autogen/oai/oai_models/chat_completion.py +13 -14
  195. autogen/oai/oai_models/chat_completion_message.py +11 -9
  196. autogen/oai/oai_models/chat_completion_message_tool_call.py +26 -3
  197. autogen/oai/oai_models/chat_completion_token_logprob.py +3 -4
  198. autogen/oai/oai_models/completion_usage.py +8 -9
  199. autogen/oai/ollama.py +19 -9
  200. autogen/oai/openai_responses.py +40 -17
  201. autogen/oai/openai_utils.py +48 -38
  202. autogen/oai/together.py +29 -14
  203. autogen/retrieve_utils.py +6 -7
  204. autogen/runtime_logging.py +5 -4
  205. autogen/token_count_utils.py +7 -4
  206. autogen/tools/contrib/time/time.py +0 -1
  207. autogen/tools/dependency_injection.py +5 -6
  208. autogen/tools/experimental/browser_use/browser_use.py +10 -10
  209. autogen/tools/experimental/code_execution/python_code_execution.py +5 -7
  210. autogen/tools/experimental/crawl4ai/crawl4ai.py +12 -15
  211. autogen/tools/experimental/deep_research/deep_research.py +9 -8
  212. autogen/tools/experimental/duckduckgo/duckduckgo_search.py +5 -11
  213. autogen/tools/experimental/firecrawl/firecrawl_tool.py +98 -115
  214. autogen/tools/experimental/google/authentication/credentials_local_provider.py +1 -1
  215. autogen/tools/experimental/google/drive/drive_functions.py +4 -4
  216. autogen/tools/experimental/google/drive/toolkit.py +5 -5
  217. autogen/tools/experimental/google_search/google_search.py +5 -5
  218. autogen/tools/experimental/google_search/youtube_search.py +5 -5
  219. autogen/tools/experimental/messageplatform/discord/discord.py +8 -12
  220. autogen/tools/experimental/messageplatform/slack/slack.py +14 -20
  221. autogen/tools/experimental/messageplatform/telegram/telegram.py +8 -12
  222. autogen/tools/experimental/perplexity/perplexity_search.py +18 -29
  223. autogen/tools/experimental/reliable/reliable.py +68 -74
  224. autogen/tools/experimental/searxng/searxng_search.py +20 -19
  225. autogen/tools/experimental/tavily/tavily_search.py +12 -19
  226. autogen/tools/experimental/web_search_preview/web_search_preview.py +13 -7
  227. autogen/tools/experimental/wikipedia/wikipedia.py +7 -10
  228. autogen/tools/function_utils.py +7 -7
  229. autogen/tools/tool.py +8 -6
  230. autogen/types.py +2 -2
  231. autogen/version.py +1 -1
  232. ag2-0.9.7.dist-info/RECORD +0 -421
  233. autogen/llm_config.py +0 -385
  234. {ag2-0.9.7.dist-info → ag2-0.9.8.post1.dist-info}/WHEEL +0 -0
  235. {ag2-0.9.7.dist-info → ag2-0.9.8.post1.dist-info}/licenses/LICENSE +0 -0
  236. {ag2-0.9.7.dist-info → ag2-0.9.8.post1.dist-info}/licenses/NOTICE.md +0 -0
autogen/oai/ollama.py CHANGED
@@ -29,12 +29,12 @@ import random
29
29
  import re
30
30
  import time
31
31
  import warnings
32
- from typing import Any, Literal, Optional, Union
32
+ from typing import Any, Literal
33
33
 
34
34
  from pydantic import BaseModel, Field, HttpUrl
35
35
 
36
36
  from ..import_utils import optional_import_block, require_optional_import
37
- from ..llm_config import LLMConfigEntry, register_llm_config
37
+ from ..llm_config.entry import LLMConfigEntry, LLMConfigEntryDict
38
38
  from .client_utils import FormatterProtocol, should_hide_tools, validate_parameter
39
39
  from .oai_models import ChatCompletion, ChatCompletionMessage, ChatCompletionMessageToolCall, Choice, CompletionUsage
40
40
 
@@ -44,10 +44,23 @@ with optional_import_block():
44
44
  from ollama import Client
45
45
 
46
46
 
47
- @register_llm_config
47
+ class OllamaEntryDict(LLMConfigEntryDict, total=False):
48
+ api_type: Literal["ollama"]
49
+ client_host: HttpUrl | None
50
+ stream: bool
51
+ num_predict: int
52
+ num_ctx: int
53
+ repeat_penalty: float
54
+ seed: int
55
+ top_k: int
56
+ hide_tools: Literal["if_all_run", "if_any_run", "never"]
57
+ native_tool_calls: bool
58
+
59
+
48
60
  class OllamaLLMConfigEntry(LLMConfigEntry):
49
61
  api_type: Literal["ollama"] = "ollama"
50
- client_host: Optional[HttpUrl] = None
62
+ # TODO: max_tokens
63
+ client_host: HttpUrl | None = None
51
64
  stream: bool = False
52
65
  num_predict: int = Field(
53
66
  default=-1,
@@ -56,9 +69,7 @@ class OllamaLLMConfigEntry(LLMConfigEntry):
56
69
  num_ctx: int = Field(default=2048)
57
70
  repeat_penalty: float = Field(default=1.1)
58
71
  seed: int = Field(default=0)
59
- temperature: float = Field(default=0.8)
60
72
  top_k: int = Field(default=40)
61
- top_p: float = Field(default=0.9)
62
73
  hide_tools: Literal["if_all_run", "if_any_run", "never"] = "never"
63
74
  native_tool_calls: bool = False
64
75
 
@@ -101,11 +112,10 @@ class OllamaClient:
101
112
  # Override using "manual_tool_call_step2" config parameter
102
113
  TOOL_CALL_MANUAL_STEP2 = " (proceed with step 2)"
103
114
 
104
- def __init__(self, response_format: Optional[Union[BaseModel, dict[str, Any]]] = None, **kwargs):
115
+ def __init__(self, response_format: BaseModel | dict[str, Any] | None = None, **kwargs):
105
116
  """Note that no api_key or environment variable is required for Ollama."""
106
-
107
117
  # Store the response format, if provided (for structured outputs)
108
- self._response_format: Optional[Union[BaseModel, dict[str, Any]]] = response_format
118
+ self._response_format: BaseModel | dict[str, Any] | None = response_format
109
119
 
110
120
  def message_retrieval(self, response) -> list:
111
121
  """Retrieve and return a list of strings or a list of Choice.Message from the response.
@@ -4,7 +4,7 @@
4
4
 
5
5
  import copy
6
6
  import warnings
7
- from typing import TYPE_CHECKING, Any, Tuple, Union
7
+ from typing import TYPE_CHECKING, Any
8
8
 
9
9
  from pydantic import BaseModel
10
10
 
@@ -48,9 +48,8 @@ VALID_SIZES = {
48
48
 
49
49
  def calculate_openai_image_cost(
50
50
  model: str = "gpt-image-1", size: str = "1024x1024", quality: str = "high"
51
- ) -> Tuple[float, str]:
52
- """
53
- Calculate the cost for a single image generation.
51
+ ) -> tuple[float, str]:
52
+ """Calculate the cost for a single image generation.
54
53
 
55
54
  Args:
56
55
  model: Model name ("gpt-image-1", "dall-e-3" or "dall-e-2")
@@ -114,7 +113,7 @@ class OpenAIResponsesClient:
114
113
  def __init__(
115
114
  self,
116
115
  client: "OpenAI",
117
- response_format: Union[BaseModel, dict[str, Any], None] = None,
116
+ response_format: BaseModel | dict[str, Any] | None = None,
118
117
  ):
119
118
  self._oai_client = client # plain openai.OpenAI instance
120
119
  self.response_format = response_format # kept for parity but unused for now
@@ -195,6 +194,12 @@ class OpenAIResponsesClient:
195
194
  delta_messages.append(m)
196
195
  return delta_messages[::-1]
197
196
 
197
+ def _parse_params(self, params: dict[str, Any]) -> None:
198
+ if "verbosity" in params:
199
+ verbosity = params.pop("verbosity")
200
+ params["text"] = {"verbosity": verbosity}
201
+ return params
202
+
198
203
  def create(self, params: dict[str, Any]) -> "Response":
199
204
  """Invoke `client.responses.create() or .parse()`.
200
205
 
@@ -246,7 +251,14 @@ class OpenAIResponsesClient:
246
251
  "output": content,
247
252
  })
248
253
  break
249
- params["input"] = input_items[::-1]
254
+
255
+ # Ensure we have at least one valid input item
256
+ if input_items:
257
+ params["input"] = input_items[::-1]
258
+ else:
259
+ # If no valid input items were created, create a default one
260
+ # This prevents the API error about missing required parameters
261
+ params["input"] = [{"role": "user", "content": [{"type": "input_text", "text": "Hello"}]}]
250
262
 
251
263
  # Initialize tools list
252
264
  tools_list = []
@@ -274,6 +286,11 @@ class OpenAIResponsesClient:
274
286
  UserWarning,
275
287
  )
276
288
 
289
+ # Validate that we have at least one of the required parameters
290
+ if not any(key in params for key in ["input", "previous_response_id", "prompt"]):
291
+ # If we still don't have any required parameters, create a minimal input
292
+ params["input"] = [{"role": "user", "content": [{"type": "input_text", "text": "Hello"}]}]
293
+
277
294
  # ------------------------------------------------------------------
278
295
  # Structured output handling - mimic OpenAIClient behaviour
279
296
  # ------------------------------------------------------------------
@@ -306,7 +323,6 @@ class OpenAIResponsesClient:
306
323
  kwargs["text_format"] = type_to_response_format_param(rf)
307
324
  if "response_format" in kwargs:
308
325
  kwargs["text_format"] = kwargs.pop("response_format")
309
-
310
326
  try:
311
327
  return self._oai_client.responses.parse(**kwargs)
312
328
  except TypeError as e:
@@ -325,22 +341,19 @@ class OpenAIResponsesClient:
325
341
  response = _create_or_parse(**params)
326
342
  self.previous_response_id = response.id
327
343
  return response
328
-
329
344
  # No structured output
345
+ params = self._parse_params(params)
330
346
  response = self._oai_client.responses.create(**params)
331
347
  self.previous_response_id = response.id
332
-
333
348
  # Accumulate image costs
334
349
  self._add_image_cost(response)
335
-
336
350
  return response
337
351
 
338
- def message_retrieval(
339
- self, response
340
- ) -> Union[list[str], list["ModelClient.ModelClientResponseProtocol.Choice.Message"]]:
352
+ def message_retrieval(self, response) -> list[str] | list["ModelClient.ModelClientResponseProtocol.Choice.Message"]:
341
353
  output = getattr(response, "output", [])
342
- content = [] # list[dict[str, Union[str, dict[str, Any]]]]]
354
+ content = []
343
355
  tool_calls = []
356
+
344
357
  for item in output:
345
358
  # Convert pydantic objects to plain dicts for uniform handling
346
359
  if hasattr(item, "model_dump"):
@@ -348,16 +361,26 @@ class OpenAIResponsesClient:
348
361
 
349
362
  item_type = item.get("type")
350
363
 
351
- # ------------------------------------------------------------------
352
- # 1) Normal messages
353
- # ------------------------------------------------------------------
364
+ # Skip reasoning items - they're not messages
365
+ if item_type == "reasoning":
366
+ continue
367
+
354
368
  if item_type == "message":
355
369
  new_item = copy.deepcopy(item)
356
370
  new_item["type"] = "text"
357
371
  new_item["role"] = "assistant"
372
+
358
373
  blocks = item.get("content", [])
359
374
  if len(blocks) == 1 and blocks[0].get("type") == "output_text":
360
375
  new_item["text"] = blocks[0]["text"]
376
+ elif len(blocks) > 0:
377
+ # Handle multiple content blocks
378
+ text_parts = []
379
+ for block in blocks:
380
+ if block.get("type") == "output_text":
381
+ text_parts.append(block.get("text", ""))
382
+ new_item["text"] = " ".join(text_parts)
383
+
361
384
  if "content" in new_item:
362
385
  del new_item["content"]
363
386
  content.append(new_item)
@@ -17,7 +17,7 @@ import time
17
17
  import warnings
18
18
  from copy import deepcopy
19
19
  from pathlib import Path
20
- from typing import TYPE_CHECKING, Any, Optional, Union
20
+ from typing import TYPE_CHECKING, Any, Union
21
21
 
22
22
  from dotenv import find_dotenv, load_dotenv
23
23
  from packaging.version import parse
@@ -27,8 +27,9 @@ if TYPE_CHECKING:
27
27
  from openai import OpenAI
28
28
  from openai.types.beta.assistant import Assistant
29
29
 
30
+ from ..llm_config import LLMConfig
31
+
30
32
  from ..doc_utils import export_module
31
- from ..llm_config import LLMConfig
32
33
 
33
34
  NON_CACHE_KEY = [
34
35
  "api_key",
@@ -58,6 +59,15 @@ OAI_PRICE1K = {
58
59
  # o3
59
60
  "o3": (0.0011, 0.0044),
60
61
  "o3-mini-2025-01-31": (0.0011, 0.0044),
62
+ # gpt-5
63
+ "gpt-5": (0.00125, 0.00125),
64
+ "gpt-5-2025-08-07": (0.00125, 0.00125),
65
+ # gpt-5-mini
66
+ "gpt-5-mini": (0.00025, 0.00025),
67
+ "gpt-5-mini-2025-08-07": (0.00025, 0.00025),
68
+ # gpt-5-nano
69
+ "gpt-5-nano": (0.00005, 0.00005),
70
+ "gpt-5-nano-2025-08-07": (0.00005, 0.00005),
61
71
  # gpt-4o
62
72
  "gpt-4o": (0.005, 0.015),
63
73
  "gpt-4o-2024-05-13": (0.005, 0.015),
@@ -157,9 +167,9 @@ def is_valid_api_key(api_key: str) -> bool:
157
167
  @export_module("autogen")
158
168
  def get_config_list(
159
169
  api_keys: list[str],
160
- base_urls: Optional[list[str]] = None,
161
- api_type: Optional[str] = None,
162
- api_version: Optional[str] = None,
170
+ base_urls: list[str] | None = None,
171
+ api_type: str | None = None,
172
+ api_version: str | None = None,
163
173
  ) -> list[dict[str, Any]]:
164
174
  """Get a list of configs for OpenAI API client.
165
175
 
@@ -208,7 +218,7 @@ def get_config_list(
208
218
 
209
219
  @export_module("autogen")
210
220
  def get_first_llm_config(
211
- llm_config: Union[LLMConfig, dict[str, Any]],
221
+ llm_config: Union["LLMConfig", dict[str, Any]],
212
222
  ) -> dict[str, Any]:
213
223
  """Get the first LLM config from the given LLM config.
214
224
 
@@ -236,12 +246,12 @@ def get_first_llm_config(
236
246
 
237
247
  @export_module("autogen")
238
248
  def config_list_openai_aoai(
239
- key_file_path: Optional[str] = ".",
240
- openai_api_key_file: Optional[str] = "key_openai.txt",
241
- aoai_api_key_file: Optional[str] = "key_aoai.txt",
242
- openai_api_base_file: Optional[str] = "base_openai.txt",
243
- aoai_api_base_file: Optional[str] = "base_aoai.txt",
244
- exclude: Optional[str] = None,
249
+ key_file_path: str | None = ".",
250
+ openai_api_key_file: str | None = "key_openai.txt",
251
+ aoai_api_key_file: str | None = "key_aoai.txt",
252
+ openai_api_base_file: str | None = "base_openai.txt",
253
+ aoai_api_base_file: str | None = "base_aoai.txt",
254
+ exclude: str | None = None,
245
255
  ) -> list[dict[str, Any]]:
246
256
  """Get a list of configs for OpenAI API client (including Azure or local model deployments that support OpenAI's chat completion API).
247
257
 
@@ -366,12 +376,12 @@ def config_list_openai_aoai(
366
376
 
367
377
  @export_module("autogen")
368
378
  def config_list_from_models(
369
- key_file_path: Optional[str] = ".",
370
- openai_api_key_file: Optional[str] = "key_openai.txt",
371
- aoai_api_key_file: Optional[str] = "key_aoai.txt",
372
- aoai_api_base_file: Optional[str] = "base_aoai.txt",
373
- exclude: Optional[str] = None,
374
- model_list: Optional[list[str]] = None,
379
+ key_file_path: str | None = ".",
380
+ openai_api_key_file: str | None = "key_openai.txt",
381
+ aoai_api_key_file: str | None = "key_aoai.txt",
382
+ aoai_api_base_file: str | None = "base_aoai.txt",
383
+ exclude: str | None = None,
384
+ model_list: list[str] | None = None,
375
385
  ) -> list[dict[str, Any]]:
376
386
  """Get a list of configs for API calls with models specified in the model list.
377
387
 
@@ -433,11 +443,11 @@ def config_list_from_models(
433
443
 
434
444
  @export_module("autogen")
435
445
  def config_list_gpt4_gpt35(
436
- key_file_path: Optional[str] = ".",
437
- openai_api_key_file: Optional[str] = "key_openai.txt",
438
- aoai_api_key_file: Optional[str] = "key_aoai.txt",
439
- aoai_api_base_file: Optional[str] = "base_aoai.txt",
440
- exclude: Optional[str] = None,
446
+ key_file_path: str | None = ".",
447
+ openai_api_key_file: str | None = "key_openai.txt",
448
+ aoai_api_key_file: str | None = "key_aoai.txt",
449
+ aoai_api_base_file: str | None = "base_aoai.txt",
450
+ exclude: str | None = None,
441
451
  ) -> list[dict[str, Any]]:
442
452
  """Get a list of configs for 'gpt-4' followed by 'gpt-3.5-turbo' API calls.
443
453
 
@@ -464,7 +474,7 @@ def config_list_gpt4_gpt35(
464
474
  @export_module("autogen")
465
475
  def filter_config(
466
476
  config_list: list[dict[str, Any]],
467
- filter_dict: Optional[dict[str, Union[list[Union[str, None]], set[Union[str, None]]]]],
477
+ filter_dict: dict[str, list[str | None] | set[str | None]] | None,
468
478
  exclude: bool = False,
469
479
  ) -> list[dict[str, Any]]:
470
480
  """Filter configuration dictionaries based on specified criteria.
@@ -621,8 +631,8 @@ def _satisfies_criteria(config_value: Any, criteria_values: Any) -> bool:
621
631
  @export_module("autogen")
622
632
  def config_list_from_json(
623
633
  env_or_file: str,
624
- file_location: Optional[str] = "",
625
- filter_dict: Optional[dict[str, Union[list[Union[str, None]], set[Union[str, None]]]]] = None,
634
+ file_location: str | None = "",
635
+ filter_dict: dict[str, list[str | None] | set[str | None]] | None = None,
626
636
  ) -> list[dict[str, Any]]:
627
637
  """Retrieves a list of API configurations from a JSON stored in an environment variable or a file.
628
638
 
@@ -690,10 +700,10 @@ def config_list_from_json(
690
700
 
691
701
 
692
702
  def get_config(
693
- api_key: Optional[str],
694
- base_url: Optional[str] = None,
695
- api_type: Optional[str] = None,
696
- api_version: Optional[str] = None,
703
+ api_key: str | None,
704
+ base_url: str | None = None,
705
+ api_type: str | None = None,
706
+ api_version: str | None = None,
697
707
  ) -> dict[str, Any]:
698
708
  """Constructs a configuration dictionary for a single model with the provided API configurations.
699
709
 
@@ -729,10 +739,10 @@ def get_config(
729
739
 
730
740
  @export_module("autogen")
731
741
  def config_list_from_dotenv(
732
- dotenv_file_path: Optional[str] = None,
733
- model_api_key_map: Optional[dict[str, Any]] = None,
734
- filter_dict: Optional[dict[str, Union[list[Union[str, None]], set[Union[str, None]]]]] = None,
735
- ) -> list[dict[str, Union[str, set[str]]]]:
742
+ dotenv_file_path: str | None = None,
743
+ model_api_key_map: dict[str, Any] | None = None,
744
+ filter_dict: dict[str, list[str | None] | set[str | None]] | None = None,
745
+ ) -> list[dict[str, str | set[str]]]:
736
746
  """Load API configurations from a specified .env file or environment variables and construct a list of configurations.
737
747
 
738
748
  This function will:
@@ -797,12 +807,12 @@ def config_list_from_dotenv(
797
807
  config_without_key_var = {k: v for k, v in config.items() if k != "api_key_env_var"}
798
808
  config_dict = get_config(api_key=api_key, **config_without_key_var)
799
809
  else:
800
- logging.warning(f"Unsupported type {type(config)} for model {model} configuration")
801
-
802
- if not config_dict["api_key"] or config_dict["api_key"].strip() == "":
803
810
  logging.warning(
804
- f"API key not found or empty for model {model}. Please ensure path to .env file is correct."
811
+ "Unsupported configuration type encountered for a model. Please check your model_api_key_map."
805
812
  )
813
+
814
+ if not config_dict["api_key"] or config_dict["api_key"].strip() == "":
815
+ logging.warning("API key not found or empty for a model. Please ensure path to .env file is correct.")
806
816
  continue # Skip this configuration and continue with the next
807
817
 
808
818
  # Add model to the configuration and append to the list
autogen/oai/together.py CHANGED
@@ -33,12 +33,13 @@ import copy
33
33
  import os
34
34
  import time
35
35
  import warnings
36
- from typing import Any, Literal, Optional, Union
36
+ from typing import Any, Literal
37
37
 
38
38
  from pydantic import Field
39
+ from typing_extensions import Unpack
39
40
 
40
41
  from ..import_utils import optional_import_block, require_optional_import
41
- from ..llm_config import LLMConfigEntry, register_llm_config
42
+ from ..llm_config.entry import LLMConfigEntry, LLMConfigEntryDict
42
43
  from .client_utils import should_hide_tools, validate_parameter
43
44
  from .oai_models import ChatCompletion, ChatCompletionMessage, ChatCompletionMessageToolCall, Choice, CompletionUsage
44
45
 
@@ -46,22 +47,36 @@ with optional_import_block():
46
47
  from together import Together
47
48
 
48
49
 
49
- @register_llm_config
50
+ class TogetherEntryDict(LLMConfigEntryDict, total=False):
51
+ api_type: Literal["together"]
52
+
53
+ stream: bool
54
+ top_k: int | None
55
+ repetition_penalty: float | None
56
+ presence_penalty: float | None
57
+ frequency_penalty: float | None
58
+ min_p: float | None
59
+ safety_model: str | None
60
+ hide_tools: Literal["if_all_run", "if_any_run", "never"]
61
+ price: list[float] | None
62
+ tool_choice: str | dict[str, str | dict[str, str]] | None
63
+
64
+
50
65
  class TogetherLLMConfigEntry(LLMConfigEntry):
51
66
  api_type: Literal["together"] = "together"
67
+
52
68
  max_tokens: int = Field(default=512, ge=0)
69
+
53
70
  stream: bool = False
54
- temperature: Optional[float] = Field(default=None)
55
- top_p: Optional[float] = Field(default=None)
56
- top_k: Optional[int] = Field(default=None)
57
- repetition_penalty: Optional[float] = Field(default=None)
58
- presence_penalty: Optional[float] = Field(default=None, ge=-2, le=2)
59
- frequency_penalty: Optional[float] = Field(default=None, ge=-2, le=2)
60
- min_p: Optional[float] = Field(default=None, ge=0, le=1)
61
- safety_model: Optional[str] = None
71
+ top_k: int | None = Field(default=None)
72
+ repetition_penalty: float | None = Field(default=None)
73
+ presence_penalty: float | None = Field(default=None, ge=-2, le=2)
74
+ frequency_penalty: float | None = Field(default=None, ge=-2, le=2)
75
+ min_p: float | None = Field(default=None, ge=0, le=1)
76
+ safety_model: str | None = None
62
77
  hide_tools: Literal["if_all_run", "if_any_run", "never"] = "never"
63
- price: Optional[list[float]] = Field(default=None, min_length=2, max_length=2)
64
- tool_choice: Optional[Union[str, dict[str, Union[str, dict[str, str]]]]] = (
78
+ price: list[float] | None = Field(default=None, min_length=2, max_length=2)
79
+ tool_choice: str | dict[str, str | dict[str, str]] | None = (
65
80
  None # dict is the tool to call: {"type": "function", "function": {"name": "my_function"}}
66
81
  )
67
82
 
@@ -72,7 +87,7 @@ class TogetherLLMConfigEntry(LLMConfigEntry):
72
87
  class TogetherClient:
73
88
  """Client for Together.AI's API."""
74
89
 
75
- def __init__(self, **kwargs):
90
+ def __init__(self, **kwargs: Unpack[TogetherEntryDict]):
76
91
  """Requires api_key or environment variable to be set
77
92
 
78
93
  Args:
autogen/retrieve_utils.py CHANGED
@@ -9,7 +9,8 @@ import hashlib
9
9
  import logging
10
10
  import os
11
11
  import re
12
- from typing import Any, Callable, Optional, Union
12
+ from collections.abc import Callable
13
+ from typing import Any
13
14
  from urllib.parse import urlparse
14
15
 
15
16
  import requests
@@ -158,11 +159,11 @@ def extract_text_from_pdf(file: str) -> str:
158
159
 
159
160
 
160
161
  def split_files_to_chunks(
161
- files: list[Union[tuple[str, str], str]],
162
+ files: list[tuple[str, str] | str],
162
163
  max_tokens: int = 4000,
163
164
  chunk_mode: str = "multi_lines",
164
165
  must_break_at_empty_line: bool = True,
165
- custom_text_split_function: Optional[Callable[[str], list[str]]] = None,
166
+ custom_text_split_function: Callable[[str], list[str]] | None = None,
166
167
  ) -> tuple[list[str], list[dict[str, Any]]]:
167
168
  """Split a list of files into chunks of max_tokens."""
168
169
  chunks = []
@@ -200,9 +201,7 @@ def split_files_to_chunks(
200
201
  return chunks, sources
201
202
 
202
203
 
203
- def get_files_from_dir(
204
- dir_path: Union[str, list[str]], types: list[str] = TEXT_FORMATS, recursive: bool = True
205
- ) -> list[Any]:
204
+ def get_files_from_dir(dir_path: str | list[str], types: list[str] = TEXT_FORMATS, recursive: bool = True) -> list[Any]:
206
205
  """Return a list of all the files in a given directory, a url, a file path or a list of them."""
207
206
  if len(types) == 0:
208
207
  raise ValueError("types cannot be empty.")
@@ -343,7 +342,7 @@ def is_url(string: str):
343
342
 
344
343
  @require_optional_import("chromadb", "retrievechat")
345
344
  def create_vector_db_from_dir(
346
- dir_path: Union[str, list[str]],
345
+ dir_path: str | list[str],
347
346
  max_tokens: int = 4000,
348
347
  client: "API" = None,
349
348
  db_path: str = "tmp/chromadb.db",
@@ -9,7 +9,8 @@ from __future__ import annotations
9
9
  import logging
10
10
  import sqlite3
11
11
  import uuid
12
- from typing import TYPE_CHECKING, Any, Callable, Literal, Optional, TypeVar
12
+ from collections.abc import Callable
13
+ from typing import TYPE_CHECKING, Any, Literal, TypeVar
13
14
 
14
15
  from .logger.base_logger import BaseLogger, LLMConfig
15
16
  from .logger.logger_factory import LoggerFactory
@@ -38,9 +39,9 @@ F = TypeVar("F", bound=Callable[..., Any])
38
39
 
39
40
 
40
41
  def start(
41
- logger: Optional[BaseLogger] = None,
42
+ logger: BaseLogger | None = None,
42
43
  logger_type: Literal["sqlite", "file"] = "sqlite",
43
- config: Optional[dict[str, Any]] = None,
44
+ config: dict[str, Any] | None = None,
44
45
  ) -> str:
45
46
  """Start logging for the runtime.
46
47
 
@@ -71,7 +72,7 @@ def log_chat_completion(
71
72
  wrapper_id: int,
72
73
  agent: str | Agent,
73
74
  request: dict[str, float | str | list[dict[str, str]]],
74
- response: str | "ChatCompletion",
75
+ response: str | ChatCompletion,
75
76
  is_cached: int,
76
77
  cost: float,
77
78
  start_time: str,
@@ -8,7 +8,7 @@
8
8
  import json
9
9
  import logging
10
10
  import re
11
- from typing import Any, Union
11
+ from typing import Any
12
12
 
13
13
  import tiktoken
14
14
 
@@ -63,6 +63,9 @@ def get_max_token_limit(model: str = "gpt-3.5-turbo-0613") -> int:
63
63
  "gpt-4o-2024-11-20": 128000,
64
64
  "gpt-4o-mini": 128000,
65
65
  "gpt-4o-mini-2024-07-18": 128000,
66
+ "gpt-5": 128000,
67
+ "gpt-5-mini": 128000,
68
+ "gpt-5-nano": 128000,
66
69
  }
67
70
  return max_token_limit[model]
68
71
 
@@ -71,7 +74,7 @@ def percentile_used(input, model="gpt-3.5-turbo-0613"):
71
74
  return count_token(input) / get_max_token_limit(model)
72
75
 
73
76
 
74
- def token_left(input: Union[str, list[str], dict[str, Any]], model="gpt-3.5-turbo-0613") -> int:
77
+ def token_left(input: str | list[str] | dict[str, Any], model="gpt-3.5-turbo-0613") -> int:
75
78
  """Count number of tokens left for an OpenAI model.
76
79
 
77
80
  Args:
@@ -84,7 +87,7 @@ def token_left(input: Union[str, list[str], dict[str, Any]], model="gpt-3.5-turb
84
87
  return get_max_token_limit(model) - count_token(input, model=model)
85
88
 
86
89
 
87
- def count_token(input: Union[str, list[str], dict[str, Any]], model: str = "gpt-3.5-turbo-0613") -> int:
90
+ def count_token(input: str | list[str] | dict[str, Any], model: str = "gpt-3.5-turbo-0613") -> int:
88
91
  """Count number of tokens used by an OpenAI model.
89
92
 
90
93
  Args:
@@ -112,7 +115,7 @@ def _num_token_from_text(text: str, model: str = "gpt-3.5-turbo-0613"):
112
115
  return len(encoding.encode(text))
113
116
 
114
117
 
115
- def _num_token_from_messages(messages: Union[list[str], dict[str, Any]], model="gpt-3.5-turbo-0613"):
118
+ def _num_token_from_messages(messages: list[str] | dict[str, Any], model="gpt-3.5-turbo-0613"):
116
119
  """Return the number of tokens used by a list of messages.
117
120
 
118
121
  retrieved from https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb/
@@ -26,7 +26,6 @@ class TimeTool(Tool):
26
26
  Args:
27
27
  date_time_format (str, optional): The format of the date and time. Defaults to "%Y-%m-%d %H:%M:%S".
28
28
  """
29
-
30
29
  self._date_time_format = date_time_format
31
30
 
32
31
  async def get_date_and_time(
@@ -6,8 +6,9 @@ import functools
6
6
  import inspect
7
7
  import sys
8
8
  from abc import ABC
9
+ from collections.abc import Callable, Iterable
9
10
  from functools import wraps
10
- from typing import TYPE_CHECKING, Any, Callable, Iterable, Optional, TypeVar, Union, get_type_hints
11
+ from typing import TYPE_CHECKING, Any, TypeVar, get_type_hints
11
12
 
12
13
  from ..agentchat import Agent
13
14
  from ..doc_utils import export_module
@@ -67,7 +68,7 @@ class ChatContext(BaseContext):
67
68
  return self._agent.chat_messages
68
69
 
69
70
  @property
70
- def last_message(self) -> Optional[dict[str, Any]]:
71
+ def last_message(self) -> dict[str, Any] | None:
71
72
  """The last message in the chat.
72
73
 
73
74
  Returns:
@@ -102,7 +103,7 @@ def Depends(x: Any) -> Any: # noqa: N802
102
103
  return FastDepends(x)
103
104
 
104
105
 
105
- def get_context_params(func: Callable[..., Any], subclass: Union[type[BaseContext], type[ChatContext]]) -> list[str]:
106
+ def get_context_params(func: Callable[..., Any], subclass: type[BaseContext] | type[ChatContext]) -> list[str]:
106
107
  """Gets the names of the context parameters in a function signature.
107
108
 
108
109
  Args:
@@ -116,9 +117,7 @@ def get_context_params(func: Callable[..., Any], subclass: Union[type[BaseContex
116
117
  return [p.name for p in sig.parameters.values() if _is_context_param(p, subclass=subclass)]
117
118
 
118
119
 
119
- def _is_context_param(
120
- param: inspect.Parameter, subclass: Union[type[BaseContext], type[ChatContext]] = BaseContext
121
- ) -> bool:
120
+ def _is_context_param(param: inspect.Parameter, subclass: type[BaseContext] | type[ChatContext] = BaseContext) -> bool:
122
121
  # param.annotation.__args__[0] is used to handle Annotated[MyContext, Depends(MyContext(b=2))]
123
122
  param_annotation = param.annotation.__args__[0] if hasattr(param.annotation, "__args__") else param.annotation
124
123
  try: