Skip to content

Commit 68c70da

Browse files
authored
fix(openai): add in output_text (#32450)
This property was deleted in `openai==1.99.2`.
1 parent 754528d commit 68c70da

File tree

2 files changed

+46
-31
lines changed

2 files changed

+46
-31
lines changed

libs/partners/openai/langchain_openai/chat_models/base.py

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ class BaseChatOpenAI(BaseChatModel):
458458
alias="api_key", default_factory=secret_from_env("OPENAI_API_KEY", default=None)
459459
)
460460
openai_api_base: Optional[str] = Field(default=None, alias="base_url")
461-
"""Base URL path for API requests, leave blank if not using a proxy or service
461+
"""Base URL path for API requests, leave blank if not using a proxy or service
462462
emulator."""
463463
openai_organization: Optional[str] = Field(default=None, alias="organization")
464464
"""Automatically inferred from env var ``OPENAI_ORG_ID`` if not provided."""
@@ -489,7 +489,7 @@ class BaseChatOpenAI(BaseChatModel):
489489
"""Whether to return logprobs."""
490490
top_logprobs: Optional[int] = None
491491
"""Number of most likely tokens to return at each token position, each with
492-
an associated log probability. `logprobs` must be set to true
492+
an associated log probability. `logprobs` must be set to true
493493
if this parameter is used."""
494494
logit_bias: Optional[dict[int, int]] = None
495495
"""Modify the likelihood of specified tokens appearing in the completion."""
@@ -507,7 +507,7 @@ class BaseChatOpenAI(BaseChatModel):
507507
508508
Reasoning models only, like OpenAI o1, o3, and o4-mini.
509509
510-
Currently supported values are low, medium, and high. Reducing reasoning effort
510+
Currently supported values are low, medium, and high. Reducing reasoning effort
511511
can result in faster responses and fewer tokens used on reasoning in a response.
512512
513513
.. versionadded:: 0.2.14
@@ -529,67 +529,67 @@ class BaseChatOpenAI(BaseChatModel):
529529
530530
"""
531531
tiktoken_model_name: Optional[str] = None
532-
"""The model name to pass to tiktoken when using this class.
533-
Tiktoken is used to count the number of tokens in documents to constrain
534-
them to be under a certain limit. By default, when set to None, this will
535-
be the same as the embedding model name. However, there are some cases
536-
where you may want to use this Embedding class with a model name not
537-
supported by tiktoken. This can include when using Azure embeddings or
538-
when using one of the many model providers that expose an OpenAI-like
539-
API but with different models. In those cases, in order to avoid erroring
532+
"""The model name to pass to tiktoken when using this class.
533+
Tiktoken is used to count the number of tokens in documents to constrain
534+
them to be under a certain limit. By default, when set to None, this will
535+
be the same as the embedding model name. However, there are some cases
536+
where you may want to use this Embedding class with a model name not
537+
supported by tiktoken. This can include when using Azure embeddings or
538+
when using one of the many model providers that expose an OpenAI-like
539+
API but with different models. In those cases, in order to avoid erroring
540540
when tiktoken is called, you can specify a model name to use here."""
541541
default_headers: Union[Mapping[str, str], None] = None
542542
default_query: Union[Mapping[str, object], None] = None
543543
# Configure a custom httpx client. See the
544544
# [httpx documentation](https://www.python-httpx.org/api/#client) for more details.
545545
http_client: Union[Any, None] = Field(default=None, exclude=True)
546-
"""Optional ``httpx.Client``. Only used for sync invocations. Must specify
546+
"""Optional ``httpx.Client``. Only used for sync invocations. Must specify
547547
``http_async_client`` as well if you'd like a custom client for async
548548
invocations.
549549
"""
550550
http_async_client: Union[Any, None] = Field(default=None, exclude=True)
551-
"""Optional ``httpx.AsyncClient``. Only used for async invocations. Must specify
551+
"""Optional ``httpx.AsyncClient``. Only used for async invocations. Must specify
552552
``http_client`` as well if you'd like a custom client for sync invocations."""
553553
stop: Optional[Union[list[str], str]] = Field(default=None, alias="stop_sequences")
554554
"""Default stop sequences."""
555555
extra_body: Optional[Mapping[str, Any]] = None
556556
"""Optional additional JSON properties to include in the request parameters when
557557
making requests to OpenAI compatible APIs, such as vLLM, LM Studio, or other
558558
providers.
559-
559+
560560
This is the recommended way to pass custom parameters that are specific to your
561561
OpenAI-compatible API provider but not part of the standard OpenAI API.
562-
562+
563563
Examples:
564564
- LM Studio TTL parameter: ``extra_body={"ttl": 300}``
565565
- vLLM custom parameters: ``extra_body={"use_beam_search": True}``
566566
- Any other provider-specific parameters
567-
567+
568568
.. note::
569-
569+
570570
Do NOT use ``model_kwargs`` for custom parameters that are not part of the
571-
standard OpenAI API, as this will cause errors when making API calls. Use
571+
standard OpenAI API, as this will cause errors when making API calls. Use
572572
``extra_body`` instead.
573573
"""
574574

575575
include_response_headers: bool = False
576576
"""Whether to include response headers in the output message ``response_metadata``.""" # noqa: E501
577577
disabled_params: Optional[dict[str, Any]] = Field(default=None)
578-
"""Parameters of the OpenAI client or chat.completions endpoint that should be
578+
"""Parameters of the OpenAI client or chat.completions endpoint that should be
579579
disabled for the given model.
580-
581-
Should be specified as ``{"param": None | ['val1', 'val2']}`` where the key is the
580+
581+
Should be specified as ``{"param": None | ['val1', 'val2']}`` where the key is the
582582
parameter and the value is either None, meaning that parameter should never be
583583
used, or it's a list of disabled values for the parameter.
584-
584+
585585
For example, older models may not support the ``'parallel_tool_calls'`` parameter at
586-
all, in which case ``disabled_params={"parallel_tool_calls": None}`` can be passed
586+
all, in which case ``disabled_params={"parallel_tool_calls": None}`` can be passed
587587
in.
588-
588+
589589
If a parameter is disabled then it will not be used by default in any methods, e.g.
590590
in :meth:`~langchain_openai.chat_models.base.ChatOpenAI.with_structured_output`.
591591
However this does not prevent a user from directly passed in the parameter during
592-
invocation.
592+
invocation.
593593
"""
594594

595595
include: Optional[list[str]] = None
@@ -3716,6 +3716,20 @@ def _construct_responses_api_input(messages: Sequence[BaseMessage]) -> list:
37163716
return input_
37173717

37183718

3719+
def _get_output_text(response: Response) -> str:
3720+
"""OpenAI SDK deleted response.output_text in 1.99.2"""
3721+
if hasattr(response, "output_text"):
3722+
return response.output_text
3723+
texts: list[str] = []
3724+
for output in response.output:
3725+
if output.type == "message":
3726+
for content in output.content:
3727+
if content.type == "output_text":
3728+
texts.append(content.text)
3729+
3730+
return "".join(texts)
3731+
3732+
37193733
def _construct_lc_result_from_responses_api(
37203734
response: Response,
37213735
schema: Optional[type[_BM]] = None,
@@ -3830,17 +3844,18 @@ def _construct_lc_result_from_responses_api(
38303844
# text_format=Foo,
38313845
# stream=True, # <-- errors
38323846
# )
3847+
output_text = _get_output_text(response)
38333848
if (
38343849
schema is not None
38353850
and "parsed" not in additional_kwargs
3836-
and response.output_text # tool calls can generate empty output text
3851+
and output_text # tool calls can generate empty output text
38373852
and response.text
38383853
and (text_config := response.text.model_dump())
38393854
and (format_ := text_config.get("format", {}))
38403855
and (format_.get("type") == "json_schema")
38413856
):
38423857
try:
3843-
parsed_dict = json.loads(response.output_text)
3858+
parsed_dict = json.loads(output_text)
38443859
if schema and _is_pydantic_class(schema):
38453860
parsed = schema(**parsed_dict)
38463861
else:

libs/partners/openai/uv.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)