Skip to content

Conversation

@roh26it
Copy link
Contributor

@roh26it roh26it commented Nov 26, 2025

Problem

When using Portkey with libraries like pydantic-ai that pass NOT_GIVEN values from the standard openai package, users encounter:

TypeError: Object of type NotGiven is not JSON serializable

This happens because Portkey's vendored OpenAI SDK defines its own NotGiven class, which is a different class from the standard openai's NotGiven. When pydantic-ai passes values using the standard openai's NOT_GIVEN, the vendored code doesn't recognize them as NotGiven instances.

Solution

Instead of defining duplicate NotGiven and Omit classes in the vendored code, we now:

  1. Try to import from the external openai package if it's installed
  2. Fall back to local definitions only if openai is not installed

This ensures that when libraries like pydantic-ai pass NOT_GIVEN values from the standard openai package, Portkey's vendored SDK recognizes them because they're the exact same class.

Testing

import openai._types as external_types
import portkey_ai._vendor.openai._types as vendored_types

# Now they're the same class
assert external_types.NotGiven is vendored_types.NotGiven  # ✓
assert external_types.NOT_GIVEN is vendored_types.NOT_GIVEN  # ✓

# isinstance checks work correctly
from portkey_ai._vendor.openai._utils import is_given, strip_not_given
assert is_given(external_types.NOT_GIVEN) == False  # ✓
assert strip_not_given({'a': 1, 'b': external_types.NOT_GIVEN}) == {'a': 1}  # ✓

When libraries like pydantic-ai pass NOT_GIVEN values from the standard
openai package, Portkey's vendored SDK now recognizes them because they
use the exact same class.

This fixes TypeError: Object of type NotGiven is not JSON serializable
errors when using pydantic-ai or similar libraries with Portkey.
@roh26it roh26it requested a review from Copilot November 26, 2025 16:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR resolves compatibility issues between Portkey's vendored OpenAI SDK and external libraries (like pydantic-ai) that use the standard openai package's NOT_GIVEN sentinel values. The fix prioritizes importing NotGiven, Omit, and NOT_GIVEN from the external openai package when available, falling back to local definitions only when openai is not installed.

Key changes:

  • Added try/except block to import NotGiven, Omit, and NOT_GIVEN from external openai package
  • Ensured compatibility by using the same class instances across packages
  • Maintained backward compatibility with standalone usage when openai is not installed

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 123 to +129

User code shouldn't need to use not_given directly.
# External openai only exports NOT_GIVEN, not the lowercase not_given
not_given = NOT_GIVEN
# External openai doesn't export lowercase omit, create from class
omit = Omit()
except ImportError:
# Fall back to defining our own (for standalone use without openai installed)
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a new instance of Omit() in line 127 may not maintain compatibility if the external openai package uses a singleton pattern for omit. Consider checking if the external package exports omit as a module-level constant and using that instead of creating a new instance.

Suggested change
User code shouldn't need to use not_given directly.
# External openai only exports NOT_GIVEN, not the lowercase not_given
not_given = NOT_GIVEN
# External openai doesn't export lowercase omit, create from class
omit = Omit()
except ImportError:
# Fall back to defining our own (for standalone use without openai installed)
# Try to import the singleton 'omit' if available
try:
from openai._types import omit as _external_omit
omit = _external_omit
except ImportError:
# If not exported, create from class
omit = Omit()
# External openai only exports NOT_GIVEN, not the lowercase not_given
not_given = NOT_GIVEN

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants