llama-index-llms-openai 0.3.2__tar.gz → 0.3.3__tar.gz
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.
- {llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/PKG-INFO +2 -2
- {llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/llama_index/llms/openai/base.py +21 -20
- {llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/llama_index/llms/openai/utils.py +66 -19
- {llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/pyproject.toml +5 -2
- {llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/README.md +0 -0
- {llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/llama_index/llms/openai/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: llama-index-llms-openai
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: llama-index llms openai integration
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: llama-index
|
|
@@ -11,7 +11,7 @@ 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-core (>=0.12.
|
|
14
|
+
Requires-Dist: llama-index-core (>=0.12.4,<0.13.0)
|
|
15
15
|
Requires-Dist: openai (>=1.40.0,<2.0.0)
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
|
{llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/llama_index/llms/openai/base.py
RENAMED
|
@@ -2,10 +2,10 @@ import functools
|
|
|
2
2
|
from typing import (
|
|
3
3
|
TYPE_CHECKING,
|
|
4
4
|
Any,
|
|
5
|
-
Generator,
|
|
6
5
|
Awaitable,
|
|
7
6
|
Callable,
|
|
8
7
|
Dict,
|
|
8
|
+
Generator,
|
|
9
9
|
List,
|
|
10
10
|
Optional,
|
|
11
11
|
Protocol,
|
|
@@ -18,6 +18,8 @@ from typing import (
|
|
|
18
18
|
|
|
19
19
|
import httpx
|
|
20
20
|
import tiktoken
|
|
21
|
+
|
|
22
|
+
import llama_index.core.instrumentation as instrument
|
|
21
23
|
from llama_index.core.base.llms.generic_utils import (
|
|
22
24
|
achat_to_completion_decorator,
|
|
23
25
|
acompletion_to_chat_decorator,
|
|
@@ -39,7 +41,11 @@ from llama_index.core.base.llms.types import (
|
|
|
39
41
|
LLMMetadata,
|
|
40
42
|
MessageRole,
|
|
41
43
|
)
|
|
42
|
-
from llama_index.core.bridge.pydantic import
|
|
44
|
+
from llama_index.core.bridge.pydantic import (
|
|
45
|
+
BaseModel,
|
|
46
|
+
Field,
|
|
47
|
+
PrivateAttr,
|
|
48
|
+
)
|
|
43
49
|
from llama_index.core.callbacks import CallbackManager
|
|
44
50
|
from llama_index.core.constants import (
|
|
45
51
|
DEFAULT_TEMPERATURE,
|
|
@@ -50,7 +56,8 @@ from llama_index.core.llms.callbacks import (
|
|
|
50
56
|
)
|
|
51
57
|
from llama_index.core.llms.function_calling import FunctionCallingLLM
|
|
52
58
|
from llama_index.core.llms.llm import ToolSelection
|
|
53
|
-
from llama_index.core.
|
|
59
|
+
from llama_index.core.llms.utils import parse_partial_json
|
|
60
|
+
from llama_index.core.types import BaseOutputParser, Model, PydanticProgramMode
|
|
54
61
|
from llama_index.llms.openai.utils import (
|
|
55
62
|
O1_MODELS,
|
|
56
63
|
OpenAIToolCall,
|
|
@@ -62,14 +69,10 @@ from llama_index.llms.openai.utils import (
|
|
|
62
69
|
is_function_calling_model,
|
|
63
70
|
openai_modelname_to_contextsize,
|
|
64
71
|
resolve_openai_credentials,
|
|
65
|
-
to_openai_message_dicts,
|
|
66
72
|
resolve_tool_choice,
|
|
73
|
+
to_openai_message_dicts,
|
|
67
74
|
update_tool_calls,
|
|
68
75
|
)
|
|
69
|
-
from llama_index.core.bridge.pydantic import (
|
|
70
|
-
BaseModel,
|
|
71
|
-
)
|
|
72
|
-
|
|
73
76
|
from openai import AsyncOpenAI, AzureOpenAI
|
|
74
77
|
from openai import OpenAI as SyncOpenAI
|
|
75
78
|
from openai.types.chat.chat_completion_chunk import (
|
|
@@ -77,9 +80,6 @@ from openai.types.chat.chat_completion_chunk import (
|
|
|
77
80
|
ChoiceDelta,
|
|
78
81
|
ChoiceDeltaToolCall,
|
|
79
82
|
)
|
|
80
|
-
from llama_index.core.llms.utils import parse_partial_json
|
|
81
|
-
|
|
82
|
-
import llama_index.core.instrumentation as instrument
|
|
83
83
|
|
|
84
84
|
dispatcher = instrument.get_dispatcher(__name__)
|
|
85
85
|
|
|
@@ -89,7 +89,7 @@ if TYPE_CHECKING:
|
|
|
89
89
|
DEFAULT_OPENAI_MODEL = "gpt-3.5-turbo"
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
def llm_retry_decorator(f: Callable[
|
|
92
|
+
def llm_retry_decorator(f: Callable[..., Any]) -> Callable[..., Any]:
|
|
93
93
|
@functools.wraps(f)
|
|
94
94
|
def wrapper(self, *args: Any, **kwargs: Any) -> Any:
|
|
95
95
|
max_retries = getattr(self, "max_retries", 0)
|
|
@@ -112,7 +112,7 @@ def llm_retry_decorator(f: Callable[[Any], Any]) -> Callable[[Any], Any]:
|
|
|
112
112
|
class Tokenizer(Protocol):
|
|
113
113
|
"""Tokenizers support an encode function that returns a list of ints."""
|
|
114
114
|
|
|
115
|
-
def encode(self, text: str) -> List[int]:
|
|
115
|
+
def encode(self, text: str) -> List[int]: # fmt: skip
|
|
116
116
|
...
|
|
117
117
|
|
|
118
118
|
|
|
@@ -828,7 +828,7 @@ class OpenAI(FunctionCallingLLM):
|
|
|
828
828
|
|
|
829
829
|
def _prepare_chat_with_tools(
|
|
830
830
|
self,
|
|
831
|
-
tools:
|
|
831
|
+
tools: Sequence["BaseTool"],
|
|
832
832
|
user_msg: Optional[Union[str, ChatMessage]] = None,
|
|
833
833
|
chat_history: Optional[List[ChatMessage]] = None,
|
|
834
834
|
verbose: bool = False,
|
|
@@ -850,9 +850,8 @@ class OpenAI(FunctionCallingLLM):
|
|
|
850
850
|
for tool_spec in tool_specs:
|
|
851
851
|
if tool_spec["type"] == "function":
|
|
852
852
|
tool_spec["function"]["strict"] = strict
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
] = False # in current openai 1.40.0 it is always false.
|
|
853
|
+
# in current openai 1.40.0 it is always false.
|
|
854
|
+
tool_spec["function"]["parameters"]["additionalProperties"] = False
|
|
856
855
|
|
|
857
856
|
if isinstance(user_msg, str):
|
|
858
857
|
user_msg = ChatMessage(role=MessageRole.USER, content=user_msg)
|
|
@@ -871,7 +870,7 @@ class OpenAI(FunctionCallingLLM):
|
|
|
871
870
|
def _validate_chat_with_tools_response(
|
|
872
871
|
self,
|
|
873
872
|
response: ChatResponse,
|
|
874
|
-
tools:
|
|
873
|
+
tools: Sequence["BaseTool"],
|
|
875
874
|
allow_parallel_tool_calls: bool = False,
|
|
876
875
|
**kwargs: Any,
|
|
877
876
|
) -> ChatResponse:
|
|
@@ -966,7 +965,7 @@ class OpenAI(FunctionCallingLLM):
|
|
|
966
965
|
return super().stream_structured_predict(*args, llm_kwargs=llm_kwargs, **kwargs)
|
|
967
966
|
|
|
968
967
|
@dispatcher.span
|
|
969
|
-
def
|
|
968
|
+
async def astream_structured_predict(
|
|
970
969
|
self, *args: Any, llm_kwargs: Optional[Dict[str, Any]] = None, **kwargs: Any
|
|
971
970
|
) -> Generator[Union[Model, List[Model]], None, None]:
|
|
972
971
|
"""Stream structured predict."""
|
|
@@ -978,4 +977,6 @@ class OpenAI(FunctionCallingLLM):
|
|
|
978
977
|
)
|
|
979
978
|
# by default structured prediction uses function calling to extract structured outputs
|
|
980
979
|
# here we force tool_choice to be required
|
|
981
|
-
return super().
|
|
980
|
+
return await super().astream_structured_predict(
|
|
981
|
+
*args, llm_kwargs=llm_kwargs, **kwargs
|
|
982
|
+
)
|
{llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/llama_index/llms/openai/utils.py
RENAMED
|
@@ -3,9 +3,6 @@ import os
|
|
|
3
3
|
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, Union
|
|
4
4
|
|
|
5
5
|
from deprecated import deprecated
|
|
6
|
-
from llama_index.core.base.llms.types import ChatMessage, LogProb, CompletionResponse
|
|
7
|
-
from llama_index.core.bridge.pydantic import BaseModel
|
|
8
|
-
from llama_index.core.base.llms.generic_utils import get_from_param_or_env
|
|
9
6
|
from tenacity import (
|
|
10
7
|
before_sleep_log,
|
|
11
8
|
retry,
|
|
@@ -18,12 +15,19 @@ from tenacity import (
|
|
|
18
15
|
from tenacity.stop import stop_base
|
|
19
16
|
|
|
20
17
|
import openai
|
|
18
|
+
from llama_index.core.base.llms.generic_utils import get_from_param_or_env
|
|
19
|
+
from llama_index.core.base.llms.types import (
|
|
20
|
+
ChatMessage,
|
|
21
|
+
ImageBlock,
|
|
22
|
+
LogProb,
|
|
23
|
+
TextBlock,
|
|
24
|
+
)
|
|
25
|
+
from llama_index.core.bridge.pydantic import BaseModel
|
|
21
26
|
from openai.types.chat import ChatCompletionMessageParam, ChatCompletionMessageToolCall
|
|
22
27
|
from openai.types.chat.chat_completion_chunk import ChoiceDeltaToolCall
|
|
23
28
|
from openai.types.chat.chat_completion_message import ChatCompletionMessage
|
|
24
29
|
from openai.types.chat.chat_completion_token_logprob import ChatCompletionTokenLogprob
|
|
25
30
|
from openai.types.completion_choice import Logprobs
|
|
26
|
-
from openai.types.completion import Completion
|
|
27
31
|
|
|
28
32
|
DEFAULT_OPENAI_API_TYPE = "open_ai"
|
|
29
33
|
DEFAULT_OPENAI_API_BASE = "https://api.openai.com/v1"
|
|
@@ -190,7 +194,8 @@ def create_retry_decorator(
|
|
|
190
194
|
|
|
191
195
|
|
|
192
196
|
def openai_modelname_to_contextsize(modelname: str) -> int:
|
|
193
|
-
"""
|
|
197
|
+
"""
|
|
198
|
+
Calculate the maximum number of tokens possible to generate for a model.
|
|
194
199
|
|
|
195
200
|
Args:
|
|
196
201
|
modelname: The modelname we want to know the context size for.
|
|
@@ -250,10 +255,35 @@ def is_function_calling_model(model: str) -> bool:
|
|
|
250
255
|
def to_openai_message_dict(
|
|
251
256
|
message: ChatMessage, drop_none: bool = False, model: Optional[str] = None
|
|
252
257
|
) -> ChatCompletionMessageParam:
|
|
253
|
-
"""Convert
|
|
258
|
+
"""Convert a ChatMessage to an OpenAI message dict."""
|
|
259
|
+
content = []
|
|
260
|
+
for block in message.blocks:
|
|
261
|
+
if isinstance(block, TextBlock):
|
|
262
|
+
content.append({"type": "text", "text": block.text})
|
|
263
|
+
elif isinstance(block, ImageBlock):
|
|
264
|
+
if block.url:
|
|
265
|
+
content.append(
|
|
266
|
+
{"type": "image_url", "image_url": {"url": str(block.url)}}
|
|
267
|
+
)
|
|
268
|
+
else:
|
|
269
|
+
img_bytes = block.resolve_image(as_base64=True).read()
|
|
270
|
+
img_str = img_bytes.decode("utf-8")
|
|
271
|
+
content.append(
|
|
272
|
+
{
|
|
273
|
+
"type": "image_url",
|
|
274
|
+
"image_url": {
|
|
275
|
+
"url": f"data:{block.image_mimetype};base64,{img_str}",
|
|
276
|
+
"detail": block.detail or "low",
|
|
277
|
+
},
|
|
278
|
+
}
|
|
279
|
+
)
|
|
280
|
+
else:
|
|
281
|
+
msg = f"Unsupported content block type: {type(block).__name__}"
|
|
282
|
+
raise ValueError(msg)
|
|
283
|
+
|
|
254
284
|
message_dict = {
|
|
255
285
|
"role": message.role.value,
|
|
256
|
-
"content":
|
|
286
|
+
"content": content,
|
|
257
287
|
}
|
|
258
288
|
|
|
259
289
|
# TODO: O1 models do not support system prompts
|
|
@@ -314,7 +344,7 @@ def from_openai_token_logprob(
|
|
|
314
344
|
LogProb(token=el.token, logprob=el.logprob, bytes=el.bytes or [])
|
|
315
345
|
for el in openai_token_logprob.top_logprobs
|
|
316
346
|
]
|
|
317
|
-
except Exception
|
|
347
|
+
except Exception:
|
|
318
348
|
print(openai_token_logprob)
|
|
319
349
|
raise
|
|
320
350
|
return result
|
|
@@ -332,7 +362,7 @@ def from_openai_token_logprobs(
|
|
|
332
362
|
|
|
333
363
|
|
|
334
364
|
def from_openai_completion_logprob(
|
|
335
|
-
openai_completion_logprob: Dict[str, float]
|
|
365
|
+
openai_completion_logprob: Dict[str, float],
|
|
336
366
|
) -> List[LogProb]:
|
|
337
367
|
"""Convert openai completion logprobs to generic list of LogProb."""
|
|
338
368
|
return [
|
|
@@ -354,11 +384,6 @@ def from_openai_completion_logprobs(
|
|
|
354
384
|
return result
|
|
355
385
|
|
|
356
386
|
|
|
357
|
-
def from_openai_completion(openai_completion: Completion) -> CompletionResponse:
|
|
358
|
-
"""Convert openai completion to CompletionResponse."""
|
|
359
|
-
text = openai_completion.choices[0].text
|
|
360
|
-
|
|
361
|
-
|
|
362
387
|
def from_openai_messages(
|
|
363
388
|
openai_messages: Sequence[ChatCompletionMessage],
|
|
364
389
|
) -> List[ChatMessage]:
|
|
@@ -370,13 +395,32 @@ def from_openai_message_dict(message_dict: dict) -> ChatMessage:
|
|
|
370
395
|
"""Convert openai message dict to generic message."""
|
|
371
396
|
role = message_dict["role"]
|
|
372
397
|
# NOTE: Azure OpenAI returns function calling messages without a content key
|
|
373
|
-
content = message_dict.get("content"
|
|
398
|
+
content = message_dict.get("content")
|
|
399
|
+
blocks = []
|
|
400
|
+
if isinstance(content, list):
|
|
401
|
+
for elem in content:
|
|
402
|
+
t = elem.get("type")
|
|
403
|
+
if t == "text":
|
|
404
|
+
blocks.append(TextBlock(text=elem.get("text")))
|
|
405
|
+
elif t == "image_url":
|
|
406
|
+
img = elem["image_url"]["url"]
|
|
407
|
+
detail = elem["image_url"]["detail"]
|
|
408
|
+
if img.startswith("data:"):
|
|
409
|
+
blocks.append(ImageBlock(image=img, detail=detail))
|
|
410
|
+
else:
|
|
411
|
+
blocks.append(ImageBlock(url=img, detail=detail))
|
|
412
|
+
else:
|
|
413
|
+
msg = f"Unsupported message type: {t}"
|
|
414
|
+
raise ValueError(msg)
|
|
415
|
+
content = None
|
|
374
416
|
|
|
375
417
|
additional_kwargs = message_dict.copy()
|
|
376
418
|
additional_kwargs.pop("role")
|
|
377
419
|
additional_kwargs.pop("content", None)
|
|
378
420
|
|
|
379
|
-
return ChatMessage(
|
|
421
|
+
return ChatMessage(
|
|
422
|
+
role=role, content=content, additional_kwargs=additional_kwargs, blocks=blocks
|
|
423
|
+
)
|
|
380
424
|
|
|
381
425
|
|
|
382
426
|
def from_openai_message_dicts(message_dicts: Sequence[dict]) -> List[ChatMessage]:
|
|
@@ -386,7 +430,8 @@ def from_openai_message_dicts(message_dicts: Sequence[dict]) -> List[ChatMessage
|
|
|
386
430
|
|
|
387
431
|
@deprecated("Deprecated in favor of `to_openai_tool`, which should be used instead.")
|
|
388
432
|
def to_openai_function(pydantic_class: Type[BaseModel]) -> Dict[str, Any]:
|
|
389
|
-
"""
|
|
433
|
+
"""
|
|
434
|
+
Deprecated in favor of `to_openai_tool`.
|
|
390
435
|
|
|
391
436
|
Convert pydantic class to OpenAI function.
|
|
392
437
|
"""
|
|
@@ -412,7 +457,8 @@ def resolve_openai_credentials(
|
|
|
412
457
|
api_base: Optional[str] = None,
|
|
413
458
|
api_version: Optional[str] = None,
|
|
414
459
|
) -> Tuple[Optional[str], str, str]:
|
|
415
|
-
"""
|
|
460
|
+
"""
|
|
461
|
+
"Resolve OpenAI credentials.
|
|
416
462
|
|
|
417
463
|
The order of precedence is:
|
|
418
464
|
1. param
|
|
@@ -443,7 +489,8 @@ def validate_openai_api_key(api_key: Optional[str] = None) -> None:
|
|
|
443
489
|
|
|
444
490
|
|
|
445
491
|
def resolve_tool_choice(tool_choice: Union[str, dict] = "auto") -> Union[str, dict]:
|
|
446
|
-
"""
|
|
492
|
+
"""
|
|
493
|
+
Resolve tool choice.
|
|
447
494
|
|
|
448
495
|
If tool_choice is a function name string, return the appropriate dict.
|
|
449
496
|
"""
|
|
@@ -29,12 +29,12 @@ exclude = ["**/BUILD"]
|
|
|
29
29
|
license = "MIT"
|
|
30
30
|
name = "llama-index-llms-openai"
|
|
31
31
|
readme = "README.md"
|
|
32
|
-
version = "0.3.
|
|
32
|
+
version = "0.3.3"
|
|
33
33
|
|
|
34
34
|
[tool.poetry.dependencies]
|
|
35
35
|
python = ">=3.9,<4.0"
|
|
36
36
|
openai = "^1.40.0"
|
|
37
|
-
llama-index-core = "^0.12.
|
|
37
|
+
llama-index-core = "^0.12.4"
|
|
38
38
|
|
|
39
39
|
[tool.poetry.group.dev.dependencies]
|
|
40
40
|
ipython = "8.10.0"
|
|
@@ -63,3 +63,6 @@ version = ">=v2.2.6"
|
|
|
63
63
|
|
|
64
64
|
[[tool.poetry.packages]]
|
|
65
65
|
include = "llama_index/"
|
|
66
|
+
|
|
67
|
+
[tool.ruff.lint.flake8-pytest-style]
|
|
68
|
+
fixture-parentheses = true
|
|
File without changes
|
{llama_index_llms_openai-0.3.2 → llama_index_llms_openai-0.3.3}/llama_index/llms/openai/__init__.py
RENAMED
|
File without changes
|