llama-index-llms-openai 0.4.3__py3-none-any.whl → 0.4.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,6 +77,7 @@ from llama_index.llms.openai.utils import (
77
77
  resolve_tool_choice,
78
78
  to_openai_message_dicts,
79
79
  update_tool_calls,
80
+ is_json_schema_supported,
80
81
  )
81
82
  from openai import AsyncOpenAI, AzureOpenAI, AsyncAzureOpenAI
82
83
  from openai import OpenAI as SyncOpenAI
@@ -1000,6 +1001,23 @@ class OpenAI(FunctionCallingLLM):
1000
1001
 
1001
1002
  return tool_selections
1002
1003
 
1004
+ def _prepare_schema(
1005
+ self, llm_kwargs: Optional[Dict[str, Any]], output_cls: Type[Model]
1006
+ ) -> Dict[str, Any]:
1007
+ from openai.resources.beta.chat.completions import _type_to_response_format
1008
+
1009
+ llm_kwargs = llm_kwargs or {}
1010
+ llm_kwargs["response_format"] = _type_to_response_format(output_cls)
1011
+ if "tool_choice" in llm_kwargs:
1012
+ del llm_kwargs["tool_choice"]
1013
+ return llm_kwargs
1014
+
1015
+ def _should_use_structure_outputs(self):
1016
+ return (
1017
+ self.pydantic_program_mode == PydanticProgramMode.DEFAULT
1018
+ and is_json_schema_supported(self.model)
1019
+ )
1020
+
1003
1021
  @dispatcher.span
1004
1022
  def structured_predict(
1005
1023
  self,
@@ -1011,11 +1029,17 @@ class OpenAI(FunctionCallingLLM):
1011
1029
  """Structured predict."""
1012
1030
  llm_kwargs = llm_kwargs or {}
1013
1031
 
1032
+ if self._should_use_structure_outputs():
1033
+ messages = self._extend_messages(prompt.format_messages(**prompt_args))
1034
+ llm_kwargs = self._prepare_schema(llm_kwargs, output_cls)
1035
+ response = self.chat(messages, **llm_kwargs)
1036
+ return output_cls.model_validate_json(str(response.message.content))
1037
+
1038
+ # when uses function calling to extract structured outputs
1039
+ # here we force tool_choice to be required
1014
1040
  llm_kwargs["tool_choice"] = (
1015
1041
  "required" if "tool_choice" not in llm_kwargs else llm_kwargs["tool_choice"]
1016
1042
  )
1017
- # by default structured prediction uses function calling to extract structured outputs
1018
- # here we force tool_choice to be required
1019
1043
  return super().structured_predict(
1020
1044
  output_cls, prompt, llm_kwargs=llm_kwargs, **prompt_args
1021
1045
  )
@@ -1031,15 +1055,91 @@ class OpenAI(FunctionCallingLLM):
1031
1055
  """Structured predict."""
1032
1056
  llm_kwargs = llm_kwargs or {}
1033
1057
 
1058
+ if self._should_use_structure_outputs():
1059
+ messages = self._extend_messages(prompt.format_messages(**prompt_args))
1060
+ llm_kwargs = self._prepare_schema(llm_kwargs, output_cls)
1061
+ response = await self.achat(messages, **llm_kwargs)
1062
+ return output_cls.model_validate_json(str(response.message.content))
1063
+
1064
+ # when uses function calling to extract structured outputs
1065
+ # here we force tool_choice to be required
1034
1066
  llm_kwargs["tool_choice"] = (
1035
1067
  "required" if "tool_choice" not in llm_kwargs else llm_kwargs["tool_choice"]
1036
1068
  )
1037
- # by default structured prediction uses function calling to extract structured outputs
1038
- # here we force tool_choice to be required
1039
1069
  return await super().astructured_predict(
1040
1070
  output_cls, prompt, llm_kwargs=llm_kwargs, **prompt_args
1041
1071
  )
1042
1072
 
1073
+ def _structured_stream_call(
1074
+ self,
1075
+ output_cls: Type[Model],
1076
+ prompt: PromptTemplate,
1077
+ llm_kwargs: Optional[Dict[str, Any]] = None,
1078
+ **prompt_args: Any,
1079
+ ) -> Generator[
1080
+ Union[Model, List[Model], "FlexibleModel", List["FlexibleModel"]], None, None
1081
+ ]:
1082
+ if self._should_use_structure_outputs():
1083
+ from llama_index.core.program.streaming_utils import (
1084
+ process_streaming_content_incremental,
1085
+ )
1086
+
1087
+ messages = self._extend_messages(prompt.format_messages(**prompt_args))
1088
+ llm_kwargs = self._prepare_schema(llm_kwargs, output_cls)
1089
+ curr = None
1090
+ for response in self.stream_chat(messages, **llm_kwargs):
1091
+ curr = process_streaming_content_incremental(response, output_cls, curr)
1092
+ yield curr
1093
+ else:
1094
+ llm_kwargs["tool_choice"] = (
1095
+ "required"
1096
+ if "tool_choice" not in llm_kwargs
1097
+ else llm_kwargs["tool_choice"]
1098
+ )
1099
+ yield from super()._structured_stream_call(
1100
+ output_cls, prompt, llm_kwargs, **prompt_args
1101
+ )
1102
+
1103
+ async def _structured_astream_call(
1104
+ self,
1105
+ output_cls: Type[Model],
1106
+ prompt: PromptTemplate,
1107
+ llm_kwargs: Optional[Dict[str, Any]] = None,
1108
+ **prompt_args: Any,
1109
+ ) -> AsyncGenerator[
1110
+ Union[Model, List[Model], "FlexibleModel", List["FlexibleModel"]], None
1111
+ ]:
1112
+ if self._should_use_structure_outputs():
1113
+
1114
+ async def gen(
1115
+ llm_kwargs=llm_kwargs,
1116
+ ) -> AsyncGenerator[
1117
+ Union[Model, List[Model], FlexibleModel, List[FlexibleModel]], None
1118
+ ]:
1119
+ from llama_index.core.program.streaming_utils import (
1120
+ process_streaming_content_incremental,
1121
+ )
1122
+
1123
+ messages = self._extend_messages(prompt.format_messages(**prompt_args))
1124
+ llm_kwargs = self._prepare_schema(llm_kwargs, output_cls)
1125
+ curr = None
1126
+ async for response in await self.astream_chat(messages, **llm_kwargs):
1127
+ curr = process_streaming_content_incremental(
1128
+ response, output_cls, curr
1129
+ )
1130
+ yield curr
1131
+
1132
+ return gen()
1133
+ else:
1134
+ llm_kwargs["tool_choice"] = (
1135
+ "required"
1136
+ if "tool_choice" not in llm_kwargs
1137
+ else llm_kwargs["tool_choice"]
1138
+ )
1139
+ return await super()._structured_astream_call(
1140
+ output_cls, prompt, llm_kwargs, **prompt_args
1141
+ )
1142
+
1043
1143
  @dispatcher.span
1044
1144
  def stream_structured_predict(
1045
1145
  self,
@@ -1051,11 +1151,6 @@ class OpenAI(FunctionCallingLLM):
1051
1151
  """Stream structured predict."""
1052
1152
  llm_kwargs = llm_kwargs or {}
1053
1153
 
1054
- llm_kwargs["tool_choice"] = (
1055
- "required" if "tool_choice" not in llm_kwargs else llm_kwargs["tool_choice"]
1056
- )
1057
- # by default structured prediction uses function calling to extract structured outputs
1058
- # here we force tool_choice to be required
1059
1154
  return super().stream_structured_predict(
1060
1155
  output_cls, prompt, llm_kwargs=llm_kwargs, **prompt_args
1061
1156
  )
@@ -1070,12 +1165,6 @@ class OpenAI(FunctionCallingLLM):
1070
1165
  ) -> AsyncGenerator[Union[Model, FlexibleModel], None]:
1071
1166
  """Stream structured predict."""
1072
1167
  llm_kwargs = llm_kwargs or {}
1073
-
1074
- llm_kwargs["tool_choice"] = (
1075
- "required" if "tool_choice" not in llm_kwargs else llm_kwargs["tool_choice"]
1076
- )
1077
- # by default structured prediction uses function calling to extract structured outputs
1078
- # here we force tool_choice to be required
1079
1168
  return await super().astream_structured_predict(
1080
1169
  output_cls, prompt, llm_kwargs=llm_kwargs, **prompt_args
1081
1170
  )
@@ -49,6 +49,8 @@ O1_MODELS: Dict[str, int] = {
49
49
  "o3-mini-2025-01-31": 200000,
50
50
  "o3": 200000,
51
51
  "o3-2025-04-16": 200000,
52
+ "o3-pro": 200000,
53
+ "o3-pro-2025-06-10": 200000,
52
54
  "o4-mini": 200000,
53
55
  "o4-mini-2025-04-16": 200000,
54
56
  }
@@ -180,6 +182,32 @@ DISCONTINUED_MODELS = {
180
182
  "code-cushman-001": 2048,
181
183
  }
182
184
 
185
+ JSON_SCHEMA_MODELS = [
186
+ "o4-mini",
187
+ "o1",
188
+ "o1-pro",
189
+ "o3",
190
+ "o3-mini",
191
+ "gpt-4.1",
192
+ "gpt-4o",
193
+ "gpt-4.1",
194
+ ]
195
+
196
+
197
+ def is_json_schema_supported(model: str) -> bool:
198
+ try:
199
+ from openai.resources.beta.chat import completions
200
+
201
+ if not hasattr(completions, "_type_to_response_format"):
202
+ return False
203
+
204
+ return not model.startswith("o1-mini") and any(
205
+ model.startswith(m) for m in JSON_SCHEMA_MODELS
206
+ )
207
+ except ImportError:
208
+ return False
209
+
210
+
183
211
  MISSING_API_KEY_ERROR_MESSAGE = """No API key found for OpenAI.
184
212
  Please set either the OPENAI_API_KEY environment variable or \
185
213
  openai.api_key prior to initialization.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llama-index-llms-openai
3
- Version: 0.4.3
3
+ Version: 0.4.5
4
4
  Summary: llama-index llms openai integration
5
5
  Author: llama-index
6
6
  License-Expression: MIT
7
7
  License-File: LICENSE
8
8
  Requires-Python: <4.0,>=3.9
9
- Requires-Dist: llama-index-core<0.13,>=0.12.37
9
+ Requires-Dist: llama-index-core<0.13,>=0.12.41
10
10
  Requires-Dist: openai<2,>=1.81.0
11
11
  Description-Content-Type: text/markdown
12
12
 
@@ -0,0 +1,9 @@
1
+ llama_index/llms/openai/__init__.py,sha256=8nmgixeXifQ4eVSgtCic54WxXqrrpXQPL4rhACWCSFs,229
2
+ llama_index/llms/openai/base.py,sha256=DhHPvef7ojecrkk_d7FwA-1Esv2iHymOEkBG0PaE4jg,42282
3
+ llama_index/llms/openai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ llama_index/llms/openai/responses.py,sha256=Tvlwhst3W_t7EQQCxtj8k-uW6iHmjQPMJ4dh23f-oWg,36182
5
+ llama_index/llms/openai/utils.py,sha256=cYfqKImb_ZwBdT6Jn7gqF84iY014pAvOkbgJt4LOfUc,28644
6
+ llama_index_llms_openai-0.4.5.dist-info/METADATA,sha256=J9M-2u-13ZR_hhz6BIS9Bs5lJWlm7TblIGvxOwNyCY8,3039
7
+ llama_index_llms_openai-0.4.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ llama_index_llms_openai-0.4.5.dist-info/licenses/LICENSE,sha256=JPQLUZD9rKvCTdu192Nk0V5PAwklIg6jANii3UmTyMs,1065
9
+ llama_index_llms_openai-0.4.5.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- llama_index/llms/openai/__init__.py,sha256=8nmgixeXifQ4eVSgtCic54WxXqrrpXQPL4rhACWCSFs,229
2
- llama_index/llms/openai/base.py,sha256=LTed9nxKpEnfha_FNDBrzNP3B1CTDFwaxGyAFUXXV5o,38856
3
- llama_index/llms/openai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- llama_index/llms/openai/responses.py,sha256=Tvlwhst3W_t7EQQCxtj8k-uW6iHmjQPMJ4dh23f-oWg,36182
5
- llama_index/llms/openai/utils.py,sha256=0xO-_6FPZRFCbW5JeqJDCMzLx3WN2_vVeAApWG74oA4,28071
6
- llama_index_llms_openai-0.4.3.dist-info/METADATA,sha256=L2d4szZKIinQcdHiojQBj52NK7c63eOuOgx9Id4-Hpg,3039
7
- llama_index_llms_openai-0.4.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- llama_index_llms_openai-0.4.3.dist-info/licenses/LICENSE,sha256=JPQLUZD9rKvCTdu192Nk0V5PAwklIg6jANii3UmTyMs,1065
9
- llama_index_llms_openai-0.4.3.dist-info/RECORD,,