llama-index-llms-openai 0.2.2__py3-none-any.whl → 0.2.4__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.
@@ -2,6 +2,7 @@ import functools
2
2
  from typing import (
3
3
  TYPE_CHECKING,
4
4
  Any,
5
+ Generator,
5
6
  Awaitable,
6
7
  Callable,
7
8
  Dict,
@@ -49,8 +50,9 @@ from llama_index.core.llms.callbacks import (
49
50
  )
50
51
  from llama_index.core.llms.function_calling import FunctionCallingLLM
51
52
  from llama_index.core.llms.llm import ToolSelection
52
- from llama_index.core.types import BaseOutputParser, PydanticProgramMode
53
+ from llama_index.core.types import BaseOutputParser, PydanticProgramMode, Model
53
54
  from llama_index.llms.openai.utils import (
55
+ O1_MODELS,
54
56
  OpenAIToolCall,
55
57
  create_retry_decorator,
56
58
  from_openai_completion_logprobs,
@@ -62,6 +64,9 @@ from llama_index.llms.openai.utils import (
62
64
  resolve_openai_credentials,
63
65
  to_openai_message_dicts,
64
66
  )
67
+ from llama_index.core.bridge.pydantic import (
68
+ BaseModel,
69
+ )
65
70
 
66
71
  from openai import AsyncOpenAI, AzureOpenAI
67
72
  from openai import OpenAI as SyncOpenAI
@@ -72,6 +77,10 @@ from openai.types.chat.chat_completion_chunk import (
72
77
  )
73
78
  from llama_index.core.llms.utils import parse_partial_json
74
79
 
80
+ import llama_index.core.instrumentation as instrument
81
+
82
+ dispatcher = instrument.get_dispatcher(__name__)
83
+
75
84
  if TYPE_CHECKING:
76
85
  from llama_index.core.tools.types import BaseTool
77
86
 
@@ -323,6 +332,10 @@ class OpenAI(FunctionCallingLLM):
323
332
  model=self._get_model_name()
324
333
  ),
325
334
  model_name=self.model,
335
+ # TODO: Temp for O1 beta
336
+ system_role=MessageRole.USER
337
+ if self.model in O1_MODELS
338
+ else MessageRole.SYSTEM,
326
339
  )
327
340
 
328
341
  @llm_chat_callback()
@@ -402,7 +415,7 @@ class OpenAI(FunctionCallingLLM):
402
415
  @llm_retry_decorator
403
416
  def _chat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:
404
417
  client = self._get_client()
405
- message_dicts = to_openai_message_dicts(messages)
418
+ message_dicts = to_openai_message_dicts(messages, model=self.model)
406
419
 
407
420
  if self.reuse_client:
408
421
  response = client.chat.completions.create(
@@ -484,7 +497,7 @@ class OpenAI(FunctionCallingLLM):
484
497
  self, messages: Sequence[ChatMessage], **kwargs: Any
485
498
  ) -> ChatResponseGen:
486
499
  client = self._get_client()
487
- message_dicts = to_openai_message_dicts(messages)
500
+ message_dicts = to_openai_message_dicts(messages, model=self.model)
488
501
 
489
502
  def gen() -> ChatResponseGen:
490
503
  content = ""
@@ -690,7 +703,7 @@ class OpenAI(FunctionCallingLLM):
690
703
  self, messages: Sequence[ChatMessage], **kwargs: Any
691
704
  ) -> ChatResponse:
692
705
  aclient = self._get_aclient()
693
- message_dicts = to_openai_message_dicts(messages)
706
+ message_dicts = to_openai_message_dicts(messages, model=self.model)
694
707
 
695
708
  if self.reuse_client:
696
709
  response = await aclient.chat.completions.create(
@@ -723,7 +736,7 @@ class OpenAI(FunctionCallingLLM):
723
736
  self, messages: Sequence[ChatMessage], **kwargs: Any
724
737
  ) -> ChatResponseAsyncGen:
725
738
  aclient = self._get_aclient()
726
- message_dicts = to_openai_message_dicts(messages)
739
+ message_dicts = to_openai_message_dicts(messages, model=self.model)
727
740
 
728
741
  async def gen() -> ChatResponseAsyncGen:
729
742
  content = ""
@@ -940,3 +953,55 @@ class OpenAI(FunctionCallingLLM):
940
953
  )
941
954
 
942
955
  return tool_selections
956
+
957
+ @dispatcher.span
958
+ def structured_predict(
959
+ self, *args: Any, llm_kwargs: Optional[Dict[str, Any]] = None, **kwargs: Any
960
+ ) -> BaseModel:
961
+ """Structured predict."""
962
+ llm_kwargs = llm_kwargs or {}
963
+ llm_kwargs["tool_choice"] = (
964
+ "required" if "tool_choice" not in llm_kwargs else llm_kwargs["tool_choice"]
965
+ )
966
+ # by default structured prediction uses function calling to extract structured outputs
967
+ # here we force tool_choice to be required
968
+ return super().structured_predict(*args, llm_kwargs=llm_kwargs, **kwargs)
969
+
970
+ @dispatcher.span
971
+ async def astructured_predict(
972
+ self, *args: Any, llm_kwargs: Optional[Dict[str, Any]] = None, **kwargs: Any
973
+ ) -> BaseModel:
974
+ """Structured predict."""
975
+ llm_kwargs = llm_kwargs or {}
976
+ llm_kwargs["tool_choice"] = (
977
+ "required" if "tool_choice" not in llm_kwargs else llm_kwargs["tool_choice"]
978
+ )
979
+ # by default structured prediction uses function calling to extract structured outputs
980
+ # here we force tool_choice to be required
981
+ return await super().astructured_predict(*args, llm_kwargs=llm_kwargs, **kwargs)
982
+
983
+ @dispatcher.span
984
+ def stream_structured_predict(
985
+ self, *args: Any, llm_kwargs: Optional[Dict[str, Any]] = None, **kwargs: Any
986
+ ) -> Generator[Union[Model, List[Model]], None, None]:
987
+ """Stream structured predict."""
988
+ llm_kwargs = llm_kwargs or {}
989
+ llm_kwargs["tool_choice"] = (
990
+ "required" if "tool_choice" not in llm_kwargs else llm_kwargs["tool_choice"]
991
+ )
992
+ # by default structured prediction uses function calling to extract structured outputs
993
+ # here we force tool_choice to be required
994
+ return super().stream_structured_predict(*args, llm_kwargs=llm_kwargs, **kwargs)
995
+
996
+ @dispatcher.span
997
+ def stream_structured_predict(
998
+ self, *args: Any, llm_kwargs: Optional[Dict[str, Any]] = None, **kwargs: Any
999
+ ) -> Generator[Union[Model, List[Model]], None, None]:
1000
+ """Stream structured predict."""
1001
+ llm_kwargs = llm_kwargs or {}
1002
+ llm_kwargs["tool_choice"] = (
1003
+ "required" if "tool_choice" not in llm_kwargs else llm_kwargs["tool_choice"]
1004
+ )
1005
+ # by default structured prediction uses function calling to extract structured outputs
1006
+ # here we force tool_choice to be required
1007
+ return super().stream_structured_predict(*args, llm_kwargs=llm_kwargs, **kwargs)
@@ -29,6 +29,10 @@ DEFAULT_OPENAI_API_TYPE = "open_ai"
29
29
  DEFAULT_OPENAI_API_BASE = "https://api.openai.com/v1"
30
30
  DEFAULT_OPENAI_API_VERSION = ""
31
31
 
32
+ O1_MODELS: Dict[str, int] = {
33
+ "o1-preview": 128000,
34
+ "o1-mini": 128000,
35
+ }
32
36
 
33
37
  GPT4_MODELS: Dict[str, int] = {
34
38
  # stable model names:
@@ -109,6 +113,7 @@ GPT3_MODELS: Dict[str, int] = {
109
113
  }
110
114
 
111
115
  ALL_AVAILABLE_MODELS = {
116
+ **O1_MODELS,
112
117
  **GPT4_MODELS,
113
118
  **TURBO_MODELS,
114
119
  **GPT3_5_MODELS,
@@ -117,6 +122,7 @@ ALL_AVAILABLE_MODELS = {
117
122
  }
118
123
 
119
124
  CHAT_MODELS = {
125
+ **O1_MODELS,
120
126
  **GPT4_MODELS,
121
127
  **TURBO_MODELS,
122
128
  **AZURE_TURBO_MODELS,
@@ -220,11 +226,15 @@ def is_chat_model(model: str) -> bool:
220
226
  def is_function_calling_model(model: str) -> bool:
221
227
  is_chat_model_ = is_chat_model(model)
222
228
  is_old = "0314" in model or "0301" in model
223
- return is_chat_model_ and not is_old
229
+
230
+ # TODO: This is temporary for openai's beta
231
+ is_o1_beta = "o1" in model
232
+
233
+ return is_chat_model_ and not is_old and not is_o1_beta
224
234
 
225
235
 
226
236
  def to_openai_message_dict(
227
- message: ChatMessage, drop_none: bool = False
237
+ message: ChatMessage, drop_none: bool = False, model: Optional[str] = None
228
238
  ) -> ChatCompletionMessageParam:
229
239
  """Convert generic message to OpenAI message dict."""
230
240
  message_dict = {
@@ -232,6 +242,11 @@ def to_openai_message_dict(
232
242
  "content": message.content,
233
243
  }
234
244
 
245
+ # TODO: O1 models do not support system prompts
246
+ if model is not None and model in O1_MODELS:
247
+ if message_dict["role"] == "system":
248
+ message_dict["role"] = "user"
249
+
235
250
  # NOTE: openai messages have additional arguments:
236
251
  # - function messages have `name`
237
252
  # - assistant messages have optional `function_call`
@@ -247,11 +262,14 @@ def to_openai_message_dict(
247
262
 
248
263
 
249
264
  def to_openai_message_dicts(
250
- messages: Sequence[ChatMessage], drop_none: bool = False
265
+ messages: Sequence[ChatMessage],
266
+ drop_none: bool = False,
267
+ model: Optional[str] = None,
251
268
  ) -> List[ChatCompletionMessageParam]:
252
269
  """Convert generic messages to OpenAI message dicts."""
253
270
  return [
254
- to_openai_message_dict(message, drop_none=drop_none) for message in messages
271
+ to_openai_message_dict(message, drop_none=drop_none, model=model)
272
+ for message in messages
255
273
  ]
256
274
 
257
275
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: llama-index-llms-openai
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: llama-index llms openai integration
5
5
  License: MIT
6
6
  Author: llama-index
@@ -11,8 +11,8 @@ Classifier: Programming Language :: Python :: 3.9
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
- Requires-Dist: llama-index-agent-openai (>=0.3.0,<0.4.0)
15
- Requires-Dist: llama-index-core (>=0.11.0,<0.12.0)
14
+ Requires-Dist: llama-index-agent-openai (>=0.3.1,<0.4.0)
15
+ Requires-Dist: llama-index-core (>=0.11.7,<0.12.0)
16
16
  Requires-Dist: openai (>=1.40.0,<2.0.0)
17
17
  Description-Content-Type: text/markdown
18
18
 
@@ -0,0 +1,6 @@
1
+ llama_index/llms/openai/__init__.py,sha256=vm3cIBSGkBFlE77GyfyN0EhpJcnJZN95QMhPN53EkbE,148
2
+ llama_index/llms/openai/base.py,sha256=5wlEeigvfvdrhlm-0EEXvwuJm2t1o6ZJ9Dl2ob8oNLk,36998
3
+ llama_index/llms/openai/utils.py,sha256=MM8xilN70w4jFXsf-aoE4HdYWD3zptLEYjpeBZ02lEc,13571
4
+ llama_index_llms_openai-0.2.4.dist-info/METADATA,sha256=_OiQkheD5dE-b24cKH-uehLz8hnEUwSTjXQgJYEcFBA,705
5
+ llama_index_llms_openai-0.2.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
6
+ llama_index_llms_openai-0.2.4.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- llama_index/llms/openai/__init__.py,sha256=vm3cIBSGkBFlE77GyfyN0EhpJcnJZN95QMhPN53EkbE,148
2
- llama_index/llms/openai/base.py,sha256=C_nxCljq-5mV8jcfE3cR7BiRE6UfJ7CxO239lCvRfcI,34064
3
- llama_index/llms/openai/utils.py,sha256=VuDXkLR_BGVqoZc9IJqiJlVloZwG9Z7s1nGPAhlbvWE,13079
4
- llama_index_llms_openai-0.2.2.dist-info/METADATA,sha256=dHi8MVPHPI2icQKVEsePMYwYCCyRbl_OXAkuq_1I2JQ,705
5
- llama_index_llms_openai-0.2.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
6
- llama_index_llms_openai-0.2.2.dist-info/RECORD,,