mirror of
https://github.com/hwchase17/langchain.git
synced 2026-06-09 10:17:00 +00:00
fix(langchain, openai): fix create_agent / response_format for Responses API (#33939)
This commit is contained in:
@@ -28,6 +28,7 @@ from langchain_tests.integration_tests.chat_models import (
|
||||
magic_function,
|
||||
)
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
from langchain_openai import ChatOpenAI
|
||||
from tests.unit_tests.fake.callbacks import FakeCallbackHandler
|
||||
@@ -1146,17 +1147,33 @@ def test_multi_party_conversation() -> None:
|
||||
assert "Bob" in response.content
|
||||
|
||||
|
||||
def test_structured_output_and_tools() -> None:
|
||||
class ResponseFormat(BaseModel):
|
||||
response: str
|
||||
explanation: str
|
||||
class ResponseFormat(BaseModel):
|
||||
response: str
|
||||
explanation: str
|
||||
|
||||
llm = ChatOpenAI(model="gpt-5-nano").bind_tools(
|
||||
[GenerateUsername], strict=True, response_format=ResponseFormat
|
||||
|
||||
class ResponseFormatDict(TypedDict):
|
||||
response: str
|
||||
explanation: str
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"schema", [ResponseFormat, ResponseFormat.model_json_schema(), ResponseFormatDict]
|
||||
)
|
||||
def test_structured_output_and_tools(schema: Any) -> None:
|
||||
llm = ChatOpenAI(model="gpt-5-nano", verbosity="low").bind_tools(
|
||||
[GenerateUsername], strict=True, response_format=schema
|
||||
)
|
||||
|
||||
response = llm.invoke("What weighs more, a pound of feathers or a pound of gold?")
|
||||
assert isinstance(response.additional_kwargs["parsed"], ResponseFormat)
|
||||
if schema == ResponseFormat:
|
||||
parsed = response.additional_kwargs["parsed"]
|
||||
assert isinstance(parsed, ResponseFormat)
|
||||
else:
|
||||
parsed = json.loads(response.text)
|
||||
assert isinstance(parsed, dict)
|
||||
assert parsed["response"]
|
||||
assert parsed["explanation"]
|
||||
|
||||
# Test streaming tool calls
|
||||
full: BaseMessageChunk | None = None
|
||||
@@ -1172,10 +1189,6 @@ def test_structured_output_and_tools() -> None:
|
||||
|
||||
|
||||
def test_tools_and_structured_output() -> None:
|
||||
class ResponseFormat(BaseModel):
|
||||
response: str
|
||||
explanation: str
|
||||
|
||||
llm = ChatOpenAI(model="gpt-5-nano").with_structured_output(
|
||||
ResponseFormat, strict=True, include_raw=True, tools=[GenerateUsername]
|
||||
)
|
||||
|
||||
@@ -318,18 +318,23 @@ async def test_parsed_dict_schema_async(schema: Any) -> None:
|
||||
assert isinstance(parsed["response"], str)
|
||||
|
||||
|
||||
def test_function_calling_and_structured_output() -> None:
|
||||
@pytest.mark.parametrize("schema", [Foo, Foo.model_json_schema(), FooDict])
|
||||
def test_function_calling_and_structured_output(schema: Any) -> None:
|
||||
def multiply(x: int, y: int) -> int:
|
||||
"""return x * y"""
|
||||
return x * y
|
||||
|
||||
llm = ChatOpenAI(model=MODEL_NAME, use_responses_api=True)
|
||||
bound_llm = llm.bind_tools([multiply], response_format=Foo, strict=True)
|
||||
bound_llm = llm.bind_tools([multiply], response_format=schema, strict=True)
|
||||
# Test structured output
|
||||
response = llm.invoke("how are ya", response_format=Foo)
|
||||
parsed = Foo(**json.loads(response.text))
|
||||
response = llm.invoke("how are ya", response_format=schema)
|
||||
if schema == Foo:
|
||||
parsed = schema(**json.loads(response.text))
|
||||
assert parsed.response
|
||||
else:
|
||||
parsed = json.loads(response.text)
|
||||
assert parsed["response"]
|
||||
assert parsed == response.additional_kwargs["parsed"]
|
||||
assert parsed.response
|
||||
|
||||
# Test function calling
|
||||
ai_msg = cast(AIMessage, bound_llm.invoke("whats 5 * 4"))
|
||||
|
||||
Reference in New Issue
Block a user