ag2 0.4.1__py3-none-any.whl → 0.4.2b1__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.4.2b1.dist-info/METADATA +19 -0
- ag2-0.4.2b1.dist-info/RECORD +6 -0
- ag2-0.4.2b1.dist-info/top_level.txt +1 -0
- ag2-0.4.1.dist-info/METADATA +0 -500
- ag2-0.4.1.dist-info/RECORD +0 -158
- ag2-0.4.1.dist-info/top_level.txt +0 -1
- autogen/__init__.py +0 -17
- autogen/_pydantic.py +0 -116
- autogen/agentchat/__init__.py +0 -42
- autogen/agentchat/agent.py +0 -142
- autogen/agentchat/assistant_agent.py +0 -85
- autogen/agentchat/chat.py +0 -306
- autogen/agentchat/contrib/__init__.py +0 -0
- autogen/agentchat/contrib/agent_builder.py +0 -788
- autogen/agentchat/contrib/agent_eval/agent_eval.py +0 -107
- autogen/agentchat/contrib/agent_eval/criterion.py +0 -47
- autogen/agentchat/contrib/agent_eval/critic_agent.py +0 -47
- autogen/agentchat/contrib/agent_eval/quantifier_agent.py +0 -42
- autogen/agentchat/contrib/agent_eval/subcritic_agent.py +0 -48
- autogen/agentchat/contrib/agent_eval/task.py +0 -43
- autogen/agentchat/contrib/agent_optimizer.py +0 -450
- autogen/agentchat/contrib/capabilities/__init__.py +0 -0
- autogen/agentchat/contrib/capabilities/agent_capability.py +0 -21
- autogen/agentchat/contrib/capabilities/generate_images.py +0 -297
- autogen/agentchat/contrib/capabilities/teachability.py +0 -406
- autogen/agentchat/contrib/capabilities/text_compressors.py +0 -72
- autogen/agentchat/contrib/capabilities/transform_messages.py +0 -92
- autogen/agentchat/contrib/capabilities/transforms.py +0 -565
- autogen/agentchat/contrib/capabilities/transforms_util.py +0 -120
- autogen/agentchat/contrib/capabilities/vision_capability.py +0 -217
- autogen/agentchat/contrib/captainagent/tools/__init__.py +0 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +0 -41
- autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +0 -29
- autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +0 -29
- autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +0 -29
- autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +0 -22
- autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +0 -31
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +0 -26
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +0 -55
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +0 -54
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +0 -39
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +0 -22
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +0 -35
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +0 -61
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +0 -62
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +0 -48
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +0 -34
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +0 -22
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +0 -36
- autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +0 -22
- autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +0 -19
- autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +0 -29
- autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +0 -32
- autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +0 -17
- autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +0 -26
- autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +0 -24
- autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +0 -28
- autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +0 -29
- autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +0 -35
- autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +0 -40
- autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +0 -23
- autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +0 -37
- autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +0 -16
- autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +0 -16
- autogen/agentchat/contrib/captainagent/tools/requirements.txt +0 -10
- autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +0 -34
- autogen/agentchat/contrib/captainagent.py +0 -490
- autogen/agentchat/contrib/gpt_assistant_agent.py +0 -545
- autogen/agentchat/contrib/graph_rag/__init__.py +0 -0
- autogen/agentchat/contrib/graph_rag/document.py +0 -30
- autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +0 -111
- autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +0 -81
- autogen/agentchat/contrib/graph_rag/graph_query_engine.py +0 -56
- autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +0 -64
- autogen/agentchat/contrib/img_utils.py +0 -390
- autogen/agentchat/contrib/llamaindex_conversable_agent.py +0 -123
- autogen/agentchat/contrib/llava_agent.py +0 -176
- autogen/agentchat/contrib/math_user_proxy_agent.py +0 -471
- autogen/agentchat/contrib/multimodal_conversable_agent.py +0 -128
- autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +0 -325
- autogen/agentchat/contrib/retrieve_assistant_agent.py +0 -56
- autogen/agentchat/contrib/retrieve_user_proxy_agent.py +0 -705
- autogen/agentchat/contrib/society_of_mind_agent.py +0 -203
- autogen/agentchat/contrib/swarm_agent.py +0 -463
- autogen/agentchat/contrib/text_analyzer_agent.py +0 -76
- autogen/agentchat/contrib/tool_retriever.py +0 -120
- autogen/agentchat/contrib/vectordb/__init__.py +0 -0
- autogen/agentchat/contrib/vectordb/base.py +0 -243
- autogen/agentchat/contrib/vectordb/chromadb.py +0 -326
- autogen/agentchat/contrib/vectordb/mongodb.py +0 -559
- autogen/agentchat/contrib/vectordb/pgvectordb.py +0 -958
- autogen/agentchat/contrib/vectordb/qdrant.py +0 -334
- autogen/agentchat/contrib/vectordb/utils.py +0 -126
- autogen/agentchat/contrib/web_surfer.py +0 -305
- autogen/agentchat/conversable_agent.py +0 -2908
- autogen/agentchat/groupchat.py +0 -1668
- autogen/agentchat/user_proxy_agent.py +0 -109
- autogen/agentchat/utils.py +0 -207
- autogen/browser_utils.py +0 -291
- autogen/cache/__init__.py +0 -10
- autogen/cache/abstract_cache_base.py +0 -78
- autogen/cache/cache.py +0 -182
- autogen/cache/cache_factory.py +0 -85
- autogen/cache/cosmos_db_cache.py +0 -150
- autogen/cache/disk_cache.py +0 -109
- autogen/cache/in_memory_cache.py +0 -61
- autogen/cache/redis_cache.py +0 -128
- autogen/code_utils.py +0 -745
- autogen/coding/__init__.py +0 -22
- autogen/coding/base.py +0 -113
- autogen/coding/docker_commandline_code_executor.py +0 -262
- autogen/coding/factory.py +0 -45
- autogen/coding/func_with_reqs.py +0 -203
- autogen/coding/jupyter/__init__.py +0 -22
- autogen/coding/jupyter/base.py +0 -32
- autogen/coding/jupyter/docker_jupyter_server.py +0 -164
- autogen/coding/jupyter/embedded_ipython_code_executor.py +0 -182
- autogen/coding/jupyter/jupyter_client.py +0 -224
- autogen/coding/jupyter/jupyter_code_executor.py +0 -161
- autogen/coding/jupyter/local_jupyter_server.py +0 -168
- autogen/coding/local_commandline_code_executor.py +0 -410
- autogen/coding/markdown_code_extractor.py +0 -44
- autogen/coding/utils.py +0 -57
- autogen/exception_utils.py +0 -46
- autogen/extensions/__init__.py +0 -0
- autogen/formatting_utils.py +0 -76
- autogen/function_utils.py +0 -362
- autogen/graph_utils.py +0 -148
- autogen/io/__init__.py +0 -15
- autogen/io/base.py +0 -105
- autogen/io/console.py +0 -43
- autogen/io/websockets.py +0 -213
- autogen/logger/__init__.py +0 -11
- autogen/logger/base_logger.py +0 -140
- autogen/logger/file_logger.py +0 -287
- autogen/logger/logger_factory.py +0 -29
- autogen/logger/logger_utils.py +0 -42
- autogen/logger/sqlite_logger.py +0 -459
- autogen/math_utils.py +0 -356
- autogen/oai/__init__.py +0 -33
- autogen/oai/anthropic.py +0 -428
- autogen/oai/bedrock.py +0 -606
- autogen/oai/cerebras.py +0 -270
- autogen/oai/client.py +0 -1148
- autogen/oai/client_utils.py +0 -167
- autogen/oai/cohere.py +0 -453
- autogen/oai/completion.py +0 -1216
- autogen/oai/gemini.py +0 -469
- autogen/oai/groq.py +0 -281
- autogen/oai/mistral.py +0 -279
- autogen/oai/ollama.py +0 -582
- autogen/oai/openai_utils.py +0 -811
- autogen/oai/together.py +0 -343
- autogen/retrieve_utils.py +0 -487
- autogen/runtime_logging.py +0 -163
- autogen/token_count_utils.py +0 -259
- autogen/types.py +0 -20
- autogen/version.py +0 -7
- {ag2-0.4.1.dist-info → ag2-0.4.2b1.dist-info}/LICENSE +0 -0
- {ag2-0.4.1.dist-info → ag2-0.4.2b1.dist-info}/NOTICE.md +0 -0
- {ag2-0.4.1.dist-info → ag2-0.4.2b1.dist-info}/WHEEL +0 -0
autogen/function_utils.py
DELETED
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
|
|
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 Any, Callable, Dict, ForwardRef, List, Optional, Set, Tuple, Type, TypeVar, Union
|
|
12
|
-
|
|
13
|
-
from pydantic import BaseModel, Field
|
|
14
|
-
from typing_extensions import Annotated, Literal, get_args, get_origin
|
|
15
|
-
|
|
16
|
-
from ._pydantic import JsonSchemaValue, evaluate_forwardref, model_dump, model_dump_json, type2schema
|
|
17
|
-
|
|
18
|
-
logger = getLogger(__name__)
|
|
19
|
-
|
|
20
|
-
T = TypeVar("T")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any:
|
|
24
|
-
"""Get the type annotation of a parameter.
|
|
25
|
-
|
|
26
|
-
Args:
|
|
27
|
-
annotation: The annotation of the parameter
|
|
28
|
-
globalns: The global namespace of the function
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
The type annotation of the parameter
|
|
32
|
-
"""
|
|
33
|
-
if isinstance(annotation, str):
|
|
34
|
-
annotation = ForwardRef(annotation)
|
|
35
|
-
annotation = evaluate_forwardref(annotation, globalns, globalns)
|
|
36
|
-
return annotation
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
|
|
40
|
-
"""Get the signature of a function with type annotations.
|
|
41
|
-
|
|
42
|
-
Args:
|
|
43
|
-
call: The function to get the signature for
|
|
44
|
-
|
|
45
|
-
Returns:
|
|
46
|
-
The signature of the function with type annotations
|
|
47
|
-
"""
|
|
48
|
-
signature = inspect.signature(call)
|
|
49
|
-
globalns = getattr(call, "__globals__", {})
|
|
50
|
-
typed_params = [
|
|
51
|
-
inspect.Parameter(
|
|
52
|
-
name=param.name,
|
|
53
|
-
kind=param.kind,
|
|
54
|
-
default=param.default,
|
|
55
|
-
annotation=get_typed_annotation(param.annotation, globalns),
|
|
56
|
-
)
|
|
57
|
-
for param in signature.parameters.values()
|
|
58
|
-
]
|
|
59
|
-
typed_signature = inspect.Signature(typed_params)
|
|
60
|
-
return typed_signature
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def get_typed_return_annotation(call: Callable[..., Any]) -> Any:
|
|
64
|
-
"""Get the return annotation of a function.
|
|
65
|
-
|
|
66
|
-
Args:
|
|
67
|
-
call: The function to get the return annotation for
|
|
68
|
-
|
|
69
|
-
Returns:
|
|
70
|
-
The return annotation of the function
|
|
71
|
-
"""
|
|
72
|
-
signature = inspect.signature(call)
|
|
73
|
-
annotation = signature.return_annotation
|
|
74
|
-
|
|
75
|
-
if annotation is inspect.Signature.empty:
|
|
76
|
-
return None
|
|
77
|
-
|
|
78
|
-
globalns = getattr(call, "__globals__", {})
|
|
79
|
-
return get_typed_annotation(annotation, globalns)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def get_param_annotations(typed_signature: inspect.Signature) -> Dict[str, Union[Annotated[Type[Any], str], Type[Any]]]:
|
|
83
|
-
"""Get the type annotations of the parameters of a function
|
|
84
|
-
|
|
85
|
-
Args:
|
|
86
|
-
typed_signature: The signature of the function with type annotations
|
|
87
|
-
|
|
88
|
-
Returns:
|
|
89
|
-
A dictionary of the type annotations of the parameters of the function
|
|
90
|
-
"""
|
|
91
|
-
return {
|
|
92
|
-
k: v.annotation for k, v in typed_signature.parameters.items() if v.annotation is not inspect.Signature.empty
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class Parameters(BaseModel):
|
|
97
|
-
"""Parameters of a function as defined by the OpenAI API"""
|
|
98
|
-
|
|
99
|
-
type: Literal["object"] = "object"
|
|
100
|
-
properties: Dict[str, JsonSchemaValue]
|
|
101
|
-
required: List[str]
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
class Function(BaseModel):
|
|
105
|
-
"""A function as defined by the OpenAI API"""
|
|
106
|
-
|
|
107
|
-
description: Annotated[str, Field(description="Description of the function")]
|
|
108
|
-
name: Annotated[str, Field(description="Name of the function")]
|
|
109
|
-
parameters: Annotated[Parameters, Field(description="Parameters of the function")]
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class ToolFunction(BaseModel):
|
|
113
|
-
"""A function under tool as defined by the OpenAI API."""
|
|
114
|
-
|
|
115
|
-
type: Literal["function"] = "function"
|
|
116
|
-
function: Annotated[Function, Field(description="Function under tool")]
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def get_parameter_json_schema(k: str, v: Any, default_values: Dict[str, Any]) -> JsonSchemaValue:
|
|
120
|
-
"""Get a JSON schema for a parameter as defined by the OpenAI API
|
|
121
|
-
|
|
122
|
-
Args:
|
|
123
|
-
k: The name of the parameter
|
|
124
|
-
v: The type of the parameter
|
|
125
|
-
default_values: The default values of the parameters of the function
|
|
126
|
-
|
|
127
|
-
Returns:
|
|
128
|
-
A Pydanitc model for the parameter
|
|
129
|
-
"""
|
|
130
|
-
|
|
131
|
-
def type2description(k: str, v: Union[Annotated[Type[Any], str], Type[Any]]) -> str:
|
|
132
|
-
# handles Annotated
|
|
133
|
-
if hasattr(v, "__metadata__"):
|
|
134
|
-
retval = v.__metadata__[0]
|
|
135
|
-
if isinstance(retval, str):
|
|
136
|
-
return retval
|
|
137
|
-
else:
|
|
138
|
-
raise ValueError(f"Invalid description {retval} for parameter {k}, should be a string.")
|
|
139
|
-
else:
|
|
140
|
-
return k
|
|
141
|
-
|
|
142
|
-
schema = type2schema(v)
|
|
143
|
-
if k in default_values:
|
|
144
|
-
dv = default_values[k]
|
|
145
|
-
schema["default"] = dv
|
|
146
|
-
|
|
147
|
-
schema["description"] = type2description(k, v)
|
|
148
|
-
|
|
149
|
-
return schema
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def get_required_params(typed_signature: inspect.Signature) -> List[str]:
|
|
153
|
-
"""Get the required parameters of a function
|
|
154
|
-
|
|
155
|
-
Args:
|
|
156
|
-
signature: The signature of the function as returned by inspect.signature
|
|
157
|
-
|
|
158
|
-
Returns:
|
|
159
|
-
A list of the required parameters of the function
|
|
160
|
-
"""
|
|
161
|
-
return [k for k, v in typed_signature.parameters.items() if v.default == inspect.Signature.empty]
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
def get_default_values(typed_signature: inspect.Signature) -> Dict[str, Any]:
|
|
165
|
-
"""Get default values of parameters of a function
|
|
166
|
-
|
|
167
|
-
Args:
|
|
168
|
-
signature: The signature of the function as returned by inspect.signature
|
|
169
|
-
|
|
170
|
-
Returns:
|
|
171
|
-
A dictionary of the default values of the parameters of the function
|
|
172
|
-
"""
|
|
173
|
-
return {k: v.default for k, v in typed_signature.parameters.items() if v.default != inspect.Signature.empty}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def get_parameters(
|
|
177
|
-
required: List[str],
|
|
178
|
-
param_annotations: Dict[str, Union[Annotated[Type[Any], str], Type[Any]]],
|
|
179
|
-
default_values: Dict[str, Any],
|
|
180
|
-
) -> Parameters:
|
|
181
|
-
"""Get the parameters of a function as defined by the OpenAI API
|
|
182
|
-
|
|
183
|
-
Args:
|
|
184
|
-
required: The required parameters of the function
|
|
185
|
-
hints: The type hints of the function as returned by typing.get_type_hints
|
|
186
|
-
|
|
187
|
-
Returns:
|
|
188
|
-
A Pydantic model for the parameters of the function
|
|
189
|
-
"""
|
|
190
|
-
return Parameters(
|
|
191
|
-
properties={
|
|
192
|
-
k: get_parameter_json_schema(k, v, default_values)
|
|
193
|
-
for k, v in param_annotations.items()
|
|
194
|
-
if v is not inspect.Signature.empty
|
|
195
|
-
},
|
|
196
|
-
required=required,
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
def get_missing_annotations(typed_signature: inspect.Signature, required: List[str]) -> Tuple[Set[str], Set[str]]:
|
|
201
|
-
"""Get the missing annotations of a function
|
|
202
|
-
|
|
203
|
-
Ignores the parameters with default values as they are not required to be annotated, but logs a warning.
|
|
204
|
-
Args:
|
|
205
|
-
typed_signature: The signature of the function with type annotations
|
|
206
|
-
required: The required parameters of the function
|
|
207
|
-
|
|
208
|
-
Returns:
|
|
209
|
-
A set of the missing annotations of the function
|
|
210
|
-
"""
|
|
211
|
-
all_missing = {k for k, v in typed_signature.parameters.items() if v.annotation is inspect.Signature.empty}
|
|
212
|
-
missing = all_missing.intersection(set(required))
|
|
213
|
-
unannotated_with_default = all_missing.difference(missing)
|
|
214
|
-
return missing, unannotated_with_default
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
def get_function_schema(f: Callable[..., Any], *, name: Optional[str] = None, description: str) -> Dict[str, Any]:
|
|
218
|
-
"""Get a JSON schema for a function as defined by the OpenAI API
|
|
219
|
-
|
|
220
|
-
Args:
|
|
221
|
-
f: The function to get the JSON schema for
|
|
222
|
-
name: The name of the function
|
|
223
|
-
description: The description of the function
|
|
224
|
-
|
|
225
|
-
Returns:
|
|
226
|
-
A JSON schema for the function
|
|
227
|
-
|
|
228
|
-
Raises:
|
|
229
|
-
TypeError: If the function is not annotated
|
|
230
|
-
|
|
231
|
-
Examples:
|
|
232
|
-
|
|
233
|
-
```python
|
|
234
|
-
def f(a: Annotated[str, "Parameter a"], b: int = 2, c: Annotated[float, "Parameter c"] = 0.1) -> None:
|
|
235
|
-
pass
|
|
236
|
-
|
|
237
|
-
get_function_schema(f, description="function f")
|
|
238
|
-
|
|
239
|
-
# {'type': 'function',
|
|
240
|
-
# 'function': {'description': 'function f',
|
|
241
|
-
# 'name': 'f',
|
|
242
|
-
# 'parameters': {'type': 'object',
|
|
243
|
-
# 'properties': {'a': {'type': 'str', 'description': 'Parameter a'},
|
|
244
|
-
# 'b': {'type': 'int', 'description': 'b'},
|
|
245
|
-
# 'c': {'type': 'float', 'description': 'Parameter c'}},
|
|
246
|
-
# 'required': ['a']}}}
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
"""
|
|
250
|
-
typed_signature = get_typed_signature(f)
|
|
251
|
-
required = get_required_params(typed_signature)
|
|
252
|
-
default_values = get_default_values(typed_signature)
|
|
253
|
-
param_annotations = get_param_annotations(typed_signature)
|
|
254
|
-
return_annotation = get_typed_return_annotation(f)
|
|
255
|
-
missing, unannotated_with_default = get_missing_annotations(typed_signature, required)
|
|
256
|
-
|
|
257
|
-
if return_annotation is None:
|
|
258
|
-
logger.warning(
|
|
259
|
-
f"The return type of the function '{f.__name__}' is not annotated. Although annotating it is "
|
|
260
|
-
+ "optional, the function should return either a string, a subclass of 'pydantic.BaseModel'."
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
if unannotated_with_default != set():
|
|
264
|
-
unannotated_with_default_s = [f"'{k}'" for k in sorted(unannotated_with_default)]
|
|
265
|
-
logger.warning(
|
|
266
|
-
f"The following parameters of the function '{f.__name__}' with default values are not annotated: "
|
|
267
|
-
+ f"{', '.join(unannotated_with_default_s)}."
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
if missing != set():
|
|
271
|
-
missing_s = [f"'{k}'" for k in sorted(missing)]
|
|
272
|
-
raise TypeError(
|
|
273
|
-
f"All parameters of the function '{f.__name__}' without default values must be annotated. "
|
|
274
|
-
+ f"The annotations are missing for the following parameters: {', '.join(missing_s)}"
|
|
275
|
-
)
|
|
276
|
-
|
|
277
|
-
fname = name if name else f.__name__
|
|
278
|
-
|
|
279
|
-
parameters = get_parameters(required, param_annotations, default_values=default_values)
|
|
280
|
-
|
|
281
|
-
function = ToolFunction(
|
|
282
|
-
function=Function(
|
|
283
|
-
description=description,
|
|
284
|
-
name=fname,
|
|
285
|
-
parameters=parameters,
|
|
286
|
-
)
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
return model_dump(function)
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
def get_load_param_if_needed_function(t: Any) -> Optional[Callable[[Dict[str, Any], Type[BaseModel]], BaseModel]]:
|
|
293
|
-
"""Get a function to load a parameter if it is a Pydantic model
|
|
294
|
-
|
|
295
|
-
Args:
|
|
296
|
-
t: The type annotation of the parameter
|
|
297
|
-
|
|
298
|
-
Returns:
|
|
299
|
-
A function to load the parameter if it is a Pydantic model, otherwise None
|
|
300
|
-
|
|
301
|
-
"""
|
|
302
|
-
if get_origin(t) is Annotated:
|
|
303
|
-
return get_load_param_if_needed_function(get_args(t)[0])
|
|
304
|
-
|
|
305
|
-
def load_base_model(v: Dict[str, Any], t: Type[BaseModel]) -> BaseModel:
|
|
306
|
-
return t(**v)
|
|
307
|
-
|
|
308
|
-
return load_base_model if isinstance(t, type) and issubclass(t, BaseModel) else None
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
def load_basemodels_if_needed(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
312
|
-
"""A decorator to load the parameters of a function if they are Pydantic models
|
|
313
|
-
|
|
314
|
-
Args:
|
|
315
|
-
func: The function with annotated parameters
|
|
316
|
-
|
|
317
|
-
Returns:
|
|
318
|
-
A function that loads the parameters before calling the original function
|
|
319
|
-
|
|
320
|
-
"""
|
|
321
|
-
# get the type annotations of the parameters
|
|
322
|
-
typed_signature = get_typed_signature(func)
|
|
323
|
-
param_annotations = get_param_annotations(typed_signature)
|
|
324
|
-
|
|
325
|
-
# get functions for loading BaseModels when needed based on the type annotations
|
|
326
|
-
kwargs_mapping_with_nones = {k: get_load_param_if_needed_function(t) for k, t in param_annotations.items()}
|
|
327
|
-
|
|
328
|
-
# remove the None values
|
|
329
|
-
kwargs_mapping = {k: f for k, f in kwargs_mapping_with_nones.items() if f is not None}
|
|
330
|
-
|
|
331
|
-
# a function that loads the parameters before calling the original function
|
|
332
|
-
@functools.wraps(func)
|
|
333
|
-
def _load_parameters_if_needed(*args: Any, **kwargs: Any) -> Any:
|
|
334
|
-
# load the BaseModels if needed
|
|
335
|
-
for k, f in kwargs_mapping.items():
|
|
336
|
-
kwargs[k] = f(kwargs[k], param_annotations[k])
|
|
337
|
-
|
|
338
|
-
# call the original function
|
|
339
|
-
return func(*args, **kwargs)
|
|
340
|
-
|
|
341
|
-
@functools.wraps(func)
|
|
342
|
-
async def _a_load_parameters_if_needed(*args: Any, **kwargs: Any) -> Any:
|
|
343
|
-
# load the BaseModels if needed
|
|
344
|
-
for k, f in kwargs_mapping.items():
|
|
345
|
-
kwargs[k] = f(kwargs[k], param_annotations[k])
|
|
346
|
-
|
|
347
|
-
# call the original function
|
|
348
|
-
return await func(*args, **kwargs)
|
|
349
|
-
|
|
350
|
-
if inspect.iscoroutinefunction(func):
|
|
351
|
-
return _a_load_parameters_if_needed
|
|
352
|
-
else:
|
|
353
|
-
return _load_parameters_if_needed
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
def serialize_to_str(x: Any) -> str:
|
|
357
|
-
if isinstance(x, str):
|
|
358
|
-
return x
|
|
359
|
-
elif isinstance(x, BaseModel):
|
|
360
|
-
return model_dump_json(x)
|
|
361
|
-
else:
|
|
362
|
-
return json.dumps(x, ensure_ascii=False)
|
autogen/graph_utils.py
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
|
|
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 logging
|
|
8
|
-
from typing import Dict, List, Optional
|
|
9
|
-
|
|
10
|
-
from autogen.agentchat import Agent
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def has_self_loops(allowed_speaker_transitions: Dict) -> bool:
|
|
14
|
-
"""
|
|
15
|
-
Returns True if there are self loops in the allowed_speaker_transitions_Dict.
|
|
16
|
-
"""
|
|
17
|
-
return any([key in value for key, value in allowed_speaker_transitions.items()])
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def check_graph_validity(
|
|
21
|
-
allowed_speaker_transitions_dict: Dict,
|
|
22
|
-
agents: List[Agent],
|
|
23
|
-
):
|
|
24
|
-
"""
|
|
25
|
-
allowed_speaker_transitions_dict: A dictionary of keys and list as values. The keys are the names of the agents, and the values are the names of the agents that the key agent can transition to.
|
|
26
|
-
agents: A list of Agents
|
|
27
|
-
|
|
28
|
-
Checks for the following:
|
|
29
|
-
Errors
|
|
30
|
-
1. The dictionary must have a structure of keys and list as values
|
|
31
|
-
2. Every key exists in agents.
|
|
32
|
-
3. Every value is a list of Agents (not string).
|
|
33
|
-
|
|
34
|
-
Warnings
|
|
35
|
-
1. Warning if there are isolated agent nodes
|
|
36
|
-
2. Warning if the set of agents in allowed_speaker_transitions do not match agents
|
|
37
|
-
3. Warning if there are duplicated agents in any values of `allowed_speaker_transitions_dict`
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
### Errors
|
|
41
|
-
|
|
42
|
-
# Check 1. The dictionary must have a structure of keys and list as values
|
|
43
|
-
if not isinstance(allowed_speaker_transitions_dict, dict):
|
|
44
|
-
raise ValueError("allowed_speaker_transitions_dict must be a dictionary.")
|
|
45
|
-
|
|
46
|
-
# All values must be lists of Agent or empty
|
|
47
|
-
if not all([isinstance(value, list) for value in allowed_speaker_transitions_dict.values()]):
|
|
48
|
-
raise ValueError("allowed_speaker_transitions_dict must be a dictionary with lists as values.")
|
|
49
|
-
|
|
50
|
-
# Check 2. Every key exists in agents
|
|
51
|
-
if not all([key in agents for key in allowed_speaker_transitions_dict.keys()]):
|
|
52
|
-
raise ValueError("allowed_speaker_transitions_dict has keys not in agents.")
|
|
53
|
-
|
|
54
|
-
# Check 3. Every value is a list of Agents or empty list (not string).
|
|
55
|
-
if not all(
|
|
56
|
-
[all([isinstance(agent, Agent) for agent in value]) for value in allowed_speaker_transitions_dict.values()]
|
|
57
|
-
):
|
|
58
|
-
raise ValueError("allowed_speaker_transitions_dict has values that are not lists of Agents.")
|
|
59
|
-
|
|
60
|
-
# Warnings
|
|
61
|
-
# Warning 1. Warning if there are isolated agent nodes, there are not incoming nor outgoing edges
|
|
62
|
-
# Concat keys if len(value) is positive
|
|
63
|
-
has_outgoing_edge = []
|
|
64
|
-
for key, agent_list in allowed_speaker_transitions_dict.items():
|
|
65
|
-
if len(agent_list) > 0:
|
|
66
|
-
has_outgoing_edge.append(key)
|
|
67
|
-
no_outgoing_edges = [agent for agent in agents if agent not in has_outgoing_edge]
|
|
68
|
-
|
|
69
|
-
# allowed_speaker_transitions_dict.values() is a list of list of Agents
|
|
70
|
-
# values_all_agents is a list of all agents in allowed_speaker_transitions_dict.values()
|
|
71
|
-
has_incoming_edge = []
|
|
72
|
-
for agent_list in allowed_speaker_transitions_dict.values():
|
|
73
|
-
if len(agent_list) > 0:
|
|
74
|
-
has_incoming_edge.extend(agent_list)
|
|
75
|
-
|
|
76
|
-
no_incoming_edges = [agent for agent in agents if agent not in has_incoming_edge]
|
|
77
|
-
|
|
78
|
-
isolated_agents = set(no_incoming_edges).intersection(set(no_outgoing_edges))
|
|
79
|
-
if len(isolated_agents) > 0:
|
|
80
|
-
logging.warning(
|
|
81
|
-
f"""Warning: There are isolated agent nodes, there are not incoming nor outgoing edges. Isolated agents: {[agent.name for agent in isolated_agents]}"""
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
# Warning 2. Warning if the set of agents in allowed_speaker_transitions do not match agents
|
|
85
|
-
# Get set of agents
|
|
86
|
-
agents_in_allowed_speaker_transitions = set(has_incoming_edge).union(set(has_outgoing_edge))
|
|
87
|
-
full_anti_join = set(agents_in_allowed_speaker_transitions).symmetric_difference(set(agents))
|
|
88
|
-
if len(full_anti_join) > 0:
|
|
89
|
-
logging.warning(
|
|
90
|
-
f"""Warning: The set of agents in allowed_speaker_transitions do not match agents. Offending agents: {[agent.name for agent in full_anti_join]}"""
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
# Warning 3. Warning if there are duplicated agents in any values of `allowed_speaker_transitions_dict`
|
|
94
|
-
for key, values in allowed_speaker_transitions_dict.items():
|
|
95
|
-
duplicates = [item for item in values if values.count(item) > 1]
|
|
96
|
-
unique_duplicates = list(set(duplicates))
|
|
97
|
-
if unique_duplicates:
|
|
98
|
-
logging.warning(
|
|
99
|
-
f"Agent '{key.name}' has duplicate elements: {[agent.name for agent in unique_duplicates]}. Please remove duplicates manually."
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def invert_disallowed_to_allowed(disallowed_speaker_transitions_dict: dict, agents: List[Agent]) -> dict:
|
|
104
|
-
"""
|
|
105
|
-
Start with a fully connected allowed_speaker_transitions_dict of all agents. Remove edges from the fully connected allowed_speaker_transitions_dict according to the disallowed_speaker_transitions_dict to form the allowed_speaker_transitions_dict.
|
|
106
|
-
"""
|
|
107
|
-
# Create a fully connected allowed_speaker_transitions_dict of all agents
|
|
108
|
-
allowed_speaker_transitions_dict = {agent: [other_agent for other_agent in agents] for agent in agents}
|
|
109
|
-
|
|
110
|
-
# Remove edges from allowed_speaker_transitions_dict according to the disallowed_speaker_transitions_dict
|
|
111
|
-
for key, value in disallowed_speaker_transitions_dict.items():
|
|
112
|
-
allowed_speaker_transitions_dict[key] = [
|
|
113
|
-
agent for agent in allowed_speaker_transitions_dict[key] if agent not in value
|
|
114
|
-
]
|
|
115
|
-
|
|
116
|
-
return allowed_speaker_transitions_dict
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def visualize_speaker_transitions_dict(
|
|
120
|
-
speaker_transitions_dict: dict, agents: List[Agent], export_path: Optional[str] = None
|
|
121
|
-
):
|
|
122
|
-
"""
|
|
123
|
-
Visualize the speaker_transitions_dict using networkx.
|
|
124
|
-
"""
|
|
125
|
-
try:
|
|
126
|
-
import matplotlib.pyplot as plt
|
|
127
|
-
import networkx as nx
|
|
128
|
-
except ImportError as e:
|
|
129
|
-
logging.fatal("Failed to import networkx or matplotlib. Try running 'pip install autogen[graphs]'")
|
|
130
|
-
raise e
|
|
131
|
-
|
|
132
|
-
G = nx.DiGraph()
|
|
133
|
-
|
|
134
|
-
# Add nodes
|
|
135
|
-
G.add_nodes_from([agent.name for agent in agents])
|
|
136
|
-
|
|
137
|
-
# Add edges
|
|
138
|
-
for key, value in speaker_transitions_dict.items():
|
|
139
|
-
for agent in value:
|
|
140
|
-
G.add_edge(key.name, agent.name)
|
|
141
|
-
|
|
142
|
-
# Visualize
|
|
143
|
-
nx.draw(G, with_labels=True, font_weight="bold")
|
|
144
|
-
|
|
145
|
-
if export_path is not None:
|
|
146
|
-
plt.savefig(export_path)
|
|
147
|
-
else:
|
|
148
|
-
plt.show()
|
autogen/io/__init__.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
|
|
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 .base import InputStream, IOStream, OutputStream
|
|
8
|
-
from .console import IOConsole
|
|
9
|
-
from .websockets import IOWebsockets
|
|
10
|
-
|
|
11
|
-
# Set the default input/output stream to the console
|
|
12
|
-
IOStream.set_global_default(IOConsole())
|
|
13
|
-
IOStream.set_default(IOConsole())
|
|
14
|
-
|
|
15
|
-
__all__ = ("IOConsole", "IOStream", "InputStream", "OutputStream", "IOWebsockets")
|
autogen/io/base.py
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
|
|
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 logging
|
|
8
|
-
from contextlib import contextmanager
|
|
9
|
-
from contextvars import ContextVar
|
|
10
|
-
from typing import Any, Iterator, Optional, Protocol, runtime_checkable
|
|
11
|
-
|
|
12
|
-
__all__ = ("OutputStream", "InputStream", "IOStream")
|
|
13
|
-
|
|
14
|
-
logger = logging.getLogger(__name__)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@runtime_checkable
|
|
18
|
-
class OutputStream(Protocol):
|
|
19
|
-
def print(self, *objects: Any, sep: str = " ", end: str = "\n", flush: bool = False) -> None:
|
|
20
|
-
"""Print data to the output stream.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
objects (any): The data to print.
|
|
24
|
-
sep (str, optional): The separator between objects. Defaults to " ".
|
|
25
|
-
end (str, optional): The end of the output. Defaults to "\n".
|
|
26
|
-
flush (bool, optional): Whether to flush the output. Defaults to False.
|
|
27
|
-
"""
|
|
28
|
-
... # pragma: no cover
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@runtime_checkable
|
|
32
|
-
class InputStream(Protocol):
|
|
33
|
-
def input(self, prompt: str = "", *, password: bool = False) -> str:
|
|
34
|
-
"""Read a line from the input stream.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
prompt (str, optional): The prompt to display. Defaults to "".
|
|
38
|
-
password (bool, optional): Whether to read a password. Defaults to False.
|
|
39
|
-
|
|
40
|
-
Returns:
|
|
41
|
-
str: The line read from the input stream.
|
|
42
|
-
|
|
43
|
-
"""
|
|
44
|
-
... # pragma: no cover
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@runtime_checkable
|
|
48
|
-
class IOStream(InputStream, OutputStream, Protocol):
|
|
49
|
-
"""A protocol for input/output streams."""
|
|
50
|
-
|
|
51
|
-
# ContextVar must be used in multithreaded or async environments
|
|
52
|
-
_default_io_stream: ContextVar[Optional["IOStream"]] = ContextVar("default_iostream", default=None)
|
|
53
|
-
_default_io_stream.set(None)
|
|
54
|
-
_global_default: Optional["IOStream"] = None
|
|
55
|
-
|
|
56
|
-
@staticmethod
|
|
57
|
-
def set_global_default(stream: "IOStream") -> None:
|
|
58
|
-
"""Set the default input/output stream.
|
|
59
|
-
|
|
60
|
-
Args:
|
|
61
|
-
stream (IOStream): The input/output stream to set as the default.
|
|
62
|
-
"""
|
|
63
|
-
IOStream._global_default = stream
|
|
64
|
-
|
|
65
|
-
@staticmethod
|
|
66
|
-
def get_global_default() -> "IOStream":
|
|
67
|
-
"""Get the default input/output stream.
|
|
68
|
-
|
|
69
|
-
Returns:
|
|
70
|
-
IOStream: The default input/output stream.
|
|
71
|
-
"""
|
|
72
|
-
if IOStream._global_default is None:
|
|
73
|
-
raise RuntimeError("No global default IOStream has been set")
|
|
74
|
-
return IOStream._global_default
|
|
75
|
-
|
|
76
|
-
@staticmethod
|
|
77
|
-
def get_default() -> "IOStream":
|
|
78
|
-
"""Get the default input/output stream.
|
|
79
|
-
|
|
80
|
-
Returns:
|
|
81
|
-
IOStream: The default input/output stream.
|
|
82
|
-
"""
|
|
83
|
-
iostream = IOStream._default_io_stream.get()
|
|
84
|
-
if iostream is None:
|
|
85
|
-
iostream = IOStream.get_global_default()
|
|
86
|
-
# Set the default IOStream of the current context (thread/cooroutine)
|
|
87
|
-
IOStream.set_default(iostream)
|
|
88
|
-
return iostream
|
|
89
|
-
|
|
90
|
-
@staticmethod
|
|
91
|
-
@contextmanager
|
|
92
|
-
def set_default(stream: Optional["IOStream"]) -> Iterator[None]:
|
|
93
|
-
"""Set the default input/output stream.
|
|
94
|
-
|
|
95
|
-
Args:
|
|
96
|
-
stream (IOStream): The input/output stream to set as the default.
|
|
97
|
-
"""
|
|
98
|
-
global _default_io_stream
|
|
99
|
-
try:
|
|
100
|
-
token = IOStream._default_io_stream.set(stream)
|
|
101
|
-
yield
|
|
102
|
-
finally:
|
|
103
|
-
IOStream._default_io_stream.reset(token)
|
|
104
|
-
|
|
105
|
-
return
|
autogen/io/console.py
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
|
|
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 getpass
|
|
8
|
-
from typing import Any
|
|
9
|
-
|
|
10
|
-
from .base import IOStream
|
|
11
|
-
|
|
12
|
-
__all__ = ("IOConsole",)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class IOConsole(IOStream):
|
|
16
|
-
"""A console input/output stream."""
|
|
17
|
-
|
|
18
|
-
def print(self, *objects: Any, sep: str = " ", end: str = "\n", flush: bool = False) -> None:
|
|
19
|
-
"""Print data to the output stream.
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
objects (any): The data to print.
|
|
23
|
-
sep (str, optional): The separator between objects. Defaults to " ".
|
|
24
|
-
end (str, optional): The end of the output. Defaults to "\n".
|
|
25
|
-
flush (bool, optional): Whether to flush the output. Defaults to False.
|
|
26
|
-
"""
|
|
27
|
-
print(*objects, sep=sep, end=end, flush=flush)
|
|
28
|
-
|
|
29
|
-
def input(self, prompt: str = "", *, password: bool = False) -> str:
|
|
30
|
-
"""Read a line from the input stream.
|
|
31
|
-
|
|
32
|
-
Args:
|
|
33
|
-
prompt (str, optional): The prompt to display. Defaults to "".
|
|
34
|
-
password (bool, optional): Whether to read a password. Defaults to False.
|
|
35
|
-
|
|
36
|
-
Returns:
|
|
37
|
-
str: The line read from the input stream.
|
|
38
|
-
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
if password:
|
|
42
|
-
return getpass.getpass(prompt if prompt != "" else "Password: ")
|
|
43
|
-
return input(prompt)
|