项目文件夹

文件
wehub-resource-sync 97e91a83f3
Ruff / Ruff (push) Has been cancelled
Test / Core Tests (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.10) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.11) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.12) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.13) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.9) (push) Has been cancelled
Test / Full Coverage (Python 3.11) (push) Has been cancelled
Test / Core Provider Tests (OpenAI) (push) Has been cancelled
Test / Core Provider Tests (Anthropic) (push) Has been cancelled
Test / Core Provider Tests (Google) (push) Has been cancelled
Test / Core Provider Tests (Other) (push) Has been cancelled
Test / Anthropic Tests (push) Has been cancelled
Test / Gemini Tests (push) Has been cancelled
Test / Google GenAI Tests (push) Has been cancelled
Test / Vertex AI Tests (push) Has been cancelled
Test / OpenAI Tests (push) Has been cancelled
Test / Writer Tests (push) Has been cancelled
Test / Auto Client Tests (push) Has been cancelled
ty / type-check (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:36:38 +08:00

233 行
6.7 KiB
Python

import os
import pytest
from typing import Optional, Union
import instructor
from pydantic import BaseModel
from .util import models, modes
from itertools import product
from instructor.v2.providers.gemini.utils import map_to_gemini_function_schema
MODEL = os.getenv("GOOGLE_GENAI_MODEL", "google/gemini-pro")
@pytest.mark.parametrize("mode,model", product(modes, models))
def test_nested(mode, model):
"""Test that nested schemas are supported."""
client = instructor.from_provider(f"google/{model}", mode=mode)
class Address(BaseModel):
street: str
city: str
class Person(BaseModel):
name: str
address: Optional[Address] = None
resp = client.chat.completions.create(
model=model,
messages=[
{
"role": "user",
"content": "John loves to go gardenning with his friends",
}
],
response_model=Person,
)
assert resp.name == "John" # type: ignore
assert resp.address is None # type: ignore
@pytest.mark.parametrize("mode,model", product(modes, models))
def test_union(mode, model):
"""Test that union types are now supported with Gemini (issue #1964)."""
client = instructor.from_provider(f"google/{model}", mode=mode)
class UserData(BaseModel):
name: str
id_value: Union[str, int]
# Union types are now supported by Google GenAI SDK
# See: https://github.com/googleapis/python-genai/issues/447
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "User name is Alice with ID 12345"}],
response_model=UserData,
)
assert response.name == "Alice"
# The ID could be returned as either str or int
assert response.id_value in ["12345", 12345]
def test_optional_types_allowed():
"""Test that Optional types are correctly mapped and don't throw errors."""
class User(BaseModel):
name: str
age: Optional[int] = None
email: Optional[str] = None
schema = User.model_json_schema()
# Should not raise an error
result = map_to_gemini_function_schema(schema)
assert result["properties"]["age"]["nullable"] is True
assert result["properties"]["email"]["nullable"] is True
assert result["required"] == ["name"]
def test_union_types_allowed_schema():
"""Test that Union types are now allowed in schema mapping (issue #1964)."""
class UserWithUnion(BaseModel):
name: str
value: Union[int, str]
schema = UserWithUnion.model_json_schema()
# Union types are now supported - should not raise
result = map_to_gemini_function_schema(schema)
# The anyOf structure should be preserved
assert "properties" in result
assert "value" in result["properties"]
assert "anyOf" in result["properties"]["value"]
@pytest.mark.parametrize(
"mode", [instructor.Mode.GENAI_STRUCTURED_OUTPUTS, instructor.Mode.GENAI_TOOLS]
)
def test_genai_api_call_with_different_types(mode):
"""Test actual API call with genai SDK using different types."""
class UserProfile(BaseModel):
name: str
age: int
email: Optional[str] = None
is_premium: bool
score: float
client = instructor.from_provider(MODEL, mode=mode)
response = client.chat.completions.create(
messages=[
{
"role": "user",
"content": "Create a user profile for John Doe, 25 years old, premium user with score 85.5",
}
],
response_model=UserProfile,
)
assert isinstance(response, UserProfile)
assert response.name == "John Doe"
assert response.email is None
@pytest.mark.parametrize(
"mode", [instructor.Mode.GENAI_STRUCTURED_OUTPUTS, instructor.Mode.GENAI_TOOLS]
)
def test_genai_api_call_with_nested_models(mode):
"""Test API call with nested models (multiple users)."""
class User(BaseModel):
name: str
age: int
department: Optional[str] = None
class UserList(BaseModel):
users: list[User]
client = instructor.from_provider(MODEL, mode=mode)
response = client.chat.completions.create(
messages=[
{
"role": "user",
"content": "Create a list of 3 employees: Alice (30, Engineering), Bob (25, Marketing), Charlie (35)",
}
],
response_model=UserList,
)
assert isinstance(response, UserList)
assert len(response.users) == 3
assert {user.name for user in response.users} == {"Alice", "Bob", "Charlie"}
assert {user.age for user in response.users} == {25, 30, 35}
assert {user.department for user in response.users} == {
None,
"Engineering",
"Marketing",
}
@pytest.mark.asyncio
@pytest.mark.parametrize(
"mode", [instructor.Mode.GENAI_STRUCTURED_OUTPUTS, instructor.Mode.GENAI_TOOLS]
)
async def test_genai_api_call_with_different_types_async(mode):
"""Test actual async API call with genai SDK using different types."""
class UserProfile(BaseModel):
name: str
age: int
email: Optional[str] = None
is_premium: bool
score: float
client = instructor.from_provider(MODEL, mode=mode, async_client=True)
response = await client.chat.completions.create(
messages=[
{
"role": "user",
"content": "Create a user profile for John Doe, 25 years old, premium user with score 85.5",
}
],
response_model=UserProfile,
)
assert isinstance(response, UserProfile)
assert response.name == "John Doe"
assert response.email is None
@pytest.mark.asyncio
@pytest.mark.parametrize(
"mode", [instructor.Mode.GENAI_STRUCTURED_OUTPUTS, instructor.Mode.GENAI_TOOLS]
)
async def test_genai_api_call_with_nested_models_async(mode):
"""Test async API call with nested models (multiple users)."""
class User(BaseModel):
name: str
age: int
department: Optional[str] = None
class UserList(BaseModel):
users: list[User]
client = instructor.from_provider(MODEL, mode=mode, async_client=True)
response = await client.chat.completions.create(
messages=[
{
"role": "user",
"content": "Create a list of 3 employees: Alice (30, Engineering), Bob (25, Marketing), Charlie (35)",
}
],
response_model=UserList,
)
assert isinstance(response, UserList)
assert len(response.users) == 3
assert {user.name for user in response.users} == {"Alice", "Bob", "Charlie"}
assert {user.age for user in response.users} == {25, 30, 35}
assert {user.department for user in response.users} == {
None,
"Engineering",
"Marketing",
}