Skip to content

Commit

Permalink
Merge branch 'main' into dummy-branch
Browse files Browse the repository at this point in the history
  • Loading branch information
kumaranvpl committed Feb 20, 2025
2 parents 98efb6a + 5ac5fe1 commit 7fde47d
Show file tree
Hide file tree
Showing 11 changed files with 384 additions and 91 deletions.
32 changes: 0 additions & 32 deletions .github/workflows/notify-codecov.yml

This file was deleted.

38 changes: 19 additions & 19 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -143,23 +143,23 @@
"filename": "autogen/oai/openai_utils.py",
"hashed_secret": "aa5bc2e0df7182f74186f26d6e9063b9d57603ec",
"is_verified": false,
"line_number": 352,
"line_number": 353,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "autogen/oai/openai_utils.py",
"hashed_secret": "cbb43d092552e9af4b21efc76bc8c49c071c1d81",
"is_verified": false,
"line_number": 353,
"line_number": 354,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "autogen/oai/openai_utils.py",
"hashed_secret": "79d8b9da0f827f788759bdbe5b9254a02c74d877",
"is_verified": false,
"line_number": 573,
"line_number": 577,
"is_secret": false
}
],
Expand Down Expand Up @@ -1035,127 +1035,127 @@
"filename": "test/oai/test_utils.py",
"hashed_secret": "f72c85879027f6160ce36e1c5074ef8207bfe105",
"is_verified": false,
"line_number": 26,
"line_number": 30,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "4c88039c5079180dacb0e29d715055d95b2b7589",
"is_verified": false,
"line_number": 35,
"line_number": 39,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "7460e665be1988cc62f1caf9d47716b07d55858c",
"is_verified": false,
"line_number": 65,
"line_number": 69,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "b5c2827eb65bf13b87130e7e3c424ba9ff07cd67",
"is_verified": false,
"line_number": 72,
"line_number": 76,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "178c7a21b087dfafc826a21b61aff284c71fd258",
"is_verified": false,
"line_number": 198,
"line_number": 202,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "aa5c90e1b80bb987f562ac30eaa1a71c832892f5",
"is_verified": false,
"line_number": 199,
"line_number": 203,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "4489f55309f29853a4075cbbdf1f18b584809726",
"is_verified": false,
"line_number": 201,
"line_number": 205,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "95cfb33d5e102631e226e7ff9da4b17d6ba5f3e4",
"is_verified": false,
"line_number": 213,
"line_number": 217,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "7943297a6a2188abe697bd1e0189fdd1274818be",
"is_verified": false,
"line_number": 215,
"line_number": 219,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "8cc86c45479a8e0bbb1ddea57d3e195b611241f2",
"is_verified": false,
"line_number": 235,
"line_number": 239,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "eda6571eea7bd0ac4553ac9d745631f1f2bec7a4",
"is_verified": false,
"line_number": 237,
"line_number": 241,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "0ad02c88ffd9754bfbfc24ade0bf8bc48d76b232",
"is_verified": false,
"line_number": 246,
"line_number": 250,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "test/oai/test_utils.py",
"hashed_secret": "11841233da3f9f37c5fa14e8b482dde913db6edf",
"is_verified": false,
"line_number": 254,
"line_number": 258,
"is_secret": false
},
{
"type": "Base64 High Entropy String",
"filename": "test/oai/test_utils.py",
"hashed_secret": "11cac88cbfa53881646b024097f531c4f234151b",
"is_verified": false,
"line_number": 432,
"line_number": 436,
"is_secret": false
},
{
"type": "OpenAI Token",
"filename": "test/oai/test_utils.py",
"hashed_secret": "8e8324e8ea2ec13efb774680c6e3850625e575e6",
"is_verified": false,
"line_number": 432,
"line_number": 436,
"is_secret": false
},
{
"type": "Base64 High Entropy String",
"filename": "test/oai/test_utils.py",
"hashed_secret": "8e2fa04ab430ff4817e87e3294f33727fc78ed6c",
"is_verified": false,
"line_number": 435,
"line_number": 439,
"is_secret": false
}
],
Expand Down
20 changes: 16 additions & 4 deletions autogen/oai/anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,10 @@ def _add_response_format_to_system(self, params: dict[str, Any]):
return

# Get the schema of the Pydantic model
schema = self._response_format.model_json_schema()
if isinstance(self._response_format, dict):
schema = self._response_format
else:
schema = self._response_format.model_json_schema()

# Add instructions for JSON formatting
format_content = f"""Please provide your response as a JSON object that matches the following schema:
Expand Down Expand Up @@ -425,16 +428,25 @@ def _extract_json_response(self, response: Message) -> Any:
json_str = content[json_start : json_end + 1]

try:
# Parse JSON and validate against the Pydantic model
# Parse JSON and validate against the Pydantic model if Pydantic model was provided
json_data = json.loads(json_str)
return self._response_format.model_validate(json_data)
if isinstance(self._response_format, dict):
return json_str
else:
return self._response_format.model_validate(json_data)

except Exception as e:
raise ValueError(f"Failed to parse response as valid JSON matching the schema for Structured Output: {e!s}")


def _format_json_response(response: Any) -> str:
"""Formats the JSON response for structured outputs using the format method if it exists."""
return response.format() if isinstance(response, FormatterProtocol) else response
if isinstance(response, str):
return response
elif isinstance(response, FormatterProtocol):
return response.format()
else:
return response.model_dump_json()


@require_optional_import("anthropic", "anthropic")
Expand Down
27 changes: 22 additions & 5 deletions autogen/oai/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
if openai.__version__ >= "1.1.0":
TOOL_ENABLED = True
ERROR = None
from openai.lib._pydantic import _ensure_strict_json_schema
else:
ERROR: Optional[ImportError] = ImportError("Please install openai>=1 and diskcache to use autogen.OpenAIWrapper.")
OpenAI = object
Expand Down Expand Up @@ -258,7 +259,9 @@ def __init__(self, config):
class OpenAIClient:
"""Follows the Client protocol and wraps the OpenAI client."""

def __init__(self, client: Union[OpenAI, AzureOpenAI], response_format: Optional[BaseModel] = None):
def __init__(
self, client: Union[OpenAI, AzureOpenAI], response_format: Union[BaseModel, dict[str, Any], None] = None
):
self._oai_client = client
self.response_format = response_format
if (
Expand Down Expand Up @@ -395,9 +398,23 @@ def create(self, params: dict[str, Any]) -> ChatCompletion:
def _create_or_parse(*args, **kwargs):
if "stream" in kwargs:
kwargs.pop("stream")
kwargs["response_format"] = type_to_response_format_param(
self.response_format or params["response_format"]
)

if isinstance(kwargs["response_format"], dict):
kwargs["response_format"] = {
"type": "json_schema",
"json_schema": {
"schema": _ensure_strict_json_schema(
kwargs["response_format"], path=(), root=kwargs["response_format"]
),
"name": "response_format",
"strict": True,
},
}
else:
kwargs["response_format"] = type_to_response_format_param(
self.response_format or params["response_format"]
)

return self._oai_client.chat.completions.create(*args, **kwargs)

create_or_parse = _create_or_parse
Expand Down Expand Up @@ -987,7 +1004,7 @@ def yes_or_no_filter(context, response):
**params,
**{"response_format": json.dumps(TypeAdapter(params["response_format"]).json_schema())},
}
if "response_format" in params
if "response_format" in params and not isinstance(params["response_format"], dict)
else params
)
request_ts = get_current_ts()
Expand Down
14 changes: 11 additions & 3 deletions autogen/oai/gemini.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,12 @@ def create(self, params: dict) -> ChatCompletion:
self._response_format = params.get("response_format")
generation_config["response_mime_type"] = "application/json"

response_schema = dict(jsonref.replace_refs(params.get("response_format").model_json_schema()))
response_format_schema_raw = params.get("response_format")

if isinstance(response_format_schema_raw, dict):
response_schema = dict(jsonref.replace_refs(response_format_schema_raw))
else:
response_schema = dict(jsonref.replace_refs(params.get("response_format").model_json_schema()))
if "$defs" in response_schema:
response_schema.pop("$defs")
generation_config["response_schema"] = response_schema
Expand Down Expand Up @@ -571,9 +576,12 @@ def _convert_json_response(self, response: str) -> Any:
return response

try:
# Parse JSON and validate against the Pydantic model
# Parse JSON and validate against the Pydantic model if Pydantic model was provided
json_data = json.loads(response)
return self._response_format.model_validate(json_data)
if isinstance(self._response_format, dict):
return json_data
else:
return self._response_format.model_validate(json_data)
except Exception as e:
raise ValueError(f"Failed to parse response as valid JSON matching the schema for Structured Output: {e!s}")

Expand Down
13 changes: 10 additions & 3 deletions autogen/oai/ollama.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,11 @@ def create(self, params: dict) -> ChatCompletion:
# https://ollama.com/blog/structured-outputs
if params.get("response_format"):
self._response_format = params["response_format"]
ollama_params["format"] = params.get("response_format").model_json_schema()
ollama_params["format"] = (
params.get("response_format").model_json_schema()
if isinstance(self._response_format, BaseModel)
else params.get("response_format")
)

# Token counts will be returned
prompt_tokens = 0
Expand Down Expand Up @@ -491,8 +495,11 @@ def _convert_json_response(self, response: str) -> Any:
return response

try:
# Parse JSON and validate against the Pydantic model
return self._response_format.model_validate_json(response)
# Parse JSON and validate against the Pydantic model if Pydantic model was provided
if isinstance(self._response_format, dict):
return response
else:
return self._response_format.model_validate_json(response)
except Exception as e:
raise ValueError(f"Failed to parse response as valid JSON matching the schema for Structured Output: {e!s}")

Expand Down
4 changes: 4 additions & 0 deletions autogen/oai/openai_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#
# Portions derived from https://github.com/microsoft/autogen are under the MIT License.
# SPDX-License-Identifier: MIT
import importlib
import importlib.metadata
import json
import logging
Expand Down Expand Up @@ -554,6 +555,9 @@ def config_list_from_json(

with open(config_list_path) as json_file:
config_list = json.load(json_file)

config_list = filter_config(config_list, filter_dict)

return filter_config(config_list, filter_dict)


Expand Down
Loading

0 comments on commit 7fde47d

Please sign in to comment.