videosdk-plugins-openai 0.0.19__py3-none-any.whl → 0.0.21__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.
Potentially problematic release.
This version of videosdk-plugins-openai might be problematic. Click here for more details.
- videosdk/plugins/openai/llm.py +49 -16
- videosdk/plugins/openai/tts.py +22 -1
- videosdk/plugins/openai/version.py +1 -1
- {videosdk_plugins_openai-0.0.19.dist-info → videosdk_plugins_openai-0.0.21.dist-info}/METADATA +2 -2
- videosdk_plugins_openai-0.0.21.dist-info/RECORD +9 -0
- videosdk_plugins_openai-0.0.19.dist-info/RECORD +0 -9
- {videosdk_plugins_openai-0.0.19.dist-info → videosdk_plugins_openai-0.0.21.dist-info}/WHEEL +0 -0
videosdk/plugins/openai/llm.py
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
from typing import Any, AsyncIterator
|
|
4
|
+
from typing import Any, AsyncIterator, List, Union
|
|
5
5
|
import json
|
|
6
6
|
|
|
7
7
|
import httpx
|
|
8
8
|
import openai
|
|
9
|
-
from videosdk.agents import
|
|
9
|
+
from videosdk.agents import (
|
|
10
|
+
LLM,
|
|
11
|
+
LLMResponse,
|
|
12
|
+
ChatContext,
|
|
13
|
+
ChatRole,
|
|
14
|
+
ChatMessage,
|
|
15
|
+
FunctionCall,
|
|
16
|
+
FunctionCallOutput,
|
|
17
|
+
ToolChoice,
|
|
18
|
+
FunctionTool,
|
|
19
|
+
is_function_tool,
|
|
20
|
+
build_openai_schema,
|
|
21
|
+
)
|
|
22
|
+
from videosdk.agents.llm.chat_context import ChatContent, ImageContent
|
|
10
23
|
|
|
11
24
|
class OpenAILLM(LLM):
|
|
12
25
|
|
|
@@ -62,35 +75,55 @@ class OpenAILLM(LLM):
|
|
|
62
75
|
Yields:
|
|
63
76
|
LLMResponse objects containing the model's responses
|
|
64
77
|
"""
|
|
78
|
+
def _format_content(content: Union[str, List[ChatContent]]):
|
|
79
|
+
if isinstance(content, str):
|
|
80
|
+
return content
|
|
81
|
+
|
|
82
|
+
formatted_parts = []
|
|
83
|
+
for part in content:
|
|
84
|
+
if isinstance(part, str):
|
|
85
|
+
formatted_parts.append({"type": "text", "text": part})
|
|
86
|
+
elif isinstance(part, ImageContent):
|
|
87
|
+
image_url_data = {"url": part.to_data_url()}
|
|
88
|
+
if part.inference_detail != "auto":
|
|
89
|
+
image_url_data["detail"] = part.inference_detail
|
|
90
|
+
formatted_parts.append(
|
|
91
|
+
{
|
|
92
|
+
"type": "image_url",
|
|
93
|
+
"image_url": image_url_data,
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
return formatted_parts
|
|
97
|
+
|
|
65
98
|
completion_params = {
|
|
66
99
|
"model": self.model,
|
|
67
100
|
"messages": [
|
|
68
101
|
{
|
|
69
102
|
"role": msg.role.value,
|
|
70
|
-
"content": msg.content,
|
|
71
|
-
**({"name": msg.name} if hasattr(msg,
|
|
72
|
-
}
|
|
73
|
-
|
|
103
|
+
"content": _format_content(msg.content),
|
|
104
|
+
**({"name": msg.name} if hasattr(msg, "name") else {}),
|
|
105
|
+
}
|
|
106
|
+
if isinstance(msg, ChatMessage)
|
|
107
|
+
else {
|
|
74
108
|
"role": "assistant",
|
|
75
109
|
"content": None,
|
|
76
|
-
"function_call": {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
} if isinstance(msg, FunctionCall) else
|
|
81
|
-
{
|
|
110
|
+
"function_call": {"name": msg.name, "arguments": msg.arguments},
|
|
111
|
+
}
|
|
112
|
+
if isinstance(msg, FunctionCall)
|
|
113
|
+
else {
|
|
82
114
|
"role": "function",
|
|
83
115
|
"name": msg.name,
|
|
84
|
-
"content": msg.output
|
|
85
|
-
}
|
|
116
|
+
"content": msg.output,
|
|
117
|
+
}
|
|
118
|
+
if isinstance(msg, FunctionCallOutput)
|
|
119
|
+
else None
|
|
86
120
|
for msg in messages.items
|
|
87
|
-
if msg is not None
|
|
121
|
+
if msg is not None
|
|
88
122
|
],
|
|
89
123
|
"temperature": self.temperature,
|
|
90
124
|
"stream": True,
|
|
91
125
|
"max_tokens": self.max_completion_tokens,
|
|
92
126
|
}
|
|
93
|
-
|
|
94
127
|
if tools:
|
|
95
128
|
formatted_tools = []
|
|
96
129
|
for tool in tools:
|
videosdk/plugins/openai/tts.py
CHANGED
|
@@ -4,6 +4,7 @@ from typing import Any, AsyncIterator, Literal, Optional, Union
|
|
|
4
4
|
import httpx
|
|
5
5
|
import os
|
|
6
6
|
import openai
|
|
7
|
+
import asyncio
|
|
7
8
|
|
|
8
9
|
from videosdk.agents import TTS
|
|
9
10
|
|
|
@@ -81,6 +82,7 @@ class OpenAITTS(TTS):
|
|
|
81
82
|
self.emit("error", "Audio track or event loop not set")
|
|
82
83
|
return
|
|
83
84
|
|
|
85
|
+
audio_data = b""
|
|
84
86
|
async with self._client.audio.speech.with_streaming_response.create(
|
|
85
87
|
model=self.model,
|
|
86
88
|
voice=voice_id or self.voice,
|
|
@@ -91,13 +93,32 @@ class OpenAITTS(TTS):
|
|
|
91
93
|
) as response:
|
|
92
94
|
async for chunk in response.iter_bytes():
|
|
93
95
|
if chunk:
|
|
94
|
-
|
|
96
|
+
audio_data += chunk
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
if audio_data:
|
|
100
|
+
await self._stream_audio_chunks(audio_data)
|
|
95
101
|
|
|
96
102
|
except openai.APIError as e:
|
|
97
103
|
self.emit("error", str(e))
|
|
98
104
|
except Exception as e:
|
|
99
105
|
self.emit("error", f"TTS synthesis failed: {str(e)}")
|
|
100
106
|
|
|
107
|
+
async def _stream_audio_chunks(self, audio_bytes: bytes) -> None:
|
|
108
|
+
"""Stream audio data in chunks for smooth playback"""
|
|
109
|
+
chunk_size = int(OPENAI_TTS_SAMPLE_RATE * OPENAI_TTS_CHANNELS * 2 * 20 / 1000)
|
|
110
|
+
|
|
111
|
+
for i in range(0, len(audio_bytes), chunk_size):
|
|
112
|
+
chunk = audio_bytes[i:i + chunk_size]
|
|
113
|
+
|
|
114
|
+
if len(chunk) < chunk_size and len(chunk) > 0:
|
|
115
|
+
padding_needed = chunk_size - len(chunk)
|
|
116
|
+
chunk += b'\x00' * padding_needed
|
|
117
|
+
|
|
118
|
+
if len(chunk) == chunk_size:
|
|
119
|
+
self.loop.create_task(self.audio_track.add_new_bytes(chunk))
|
|
120
|
+
await asyncio.sleep(0.001)
|
|
121
|
+
|
|
101
122
|
async def aclose(self) -> None:
|
|
102
123
|
"""Cleanup resources"""
|
|
103
124
|
await self._client.close()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.0.
|
|
1
|
+
__version__ = "0.0.21"
|
{videosdk_plugins_openai-0.0.19.dist-info → videosdk_plugins_openai-0.0.21.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: videosdk-plugins-openai
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.21
|
|
4
4
|
Summary: VideoSDK Agent Framework plugin for OpenAI services
|
|
5
5
|
Author: videosdk
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -13,7 +13,7 @@ Classifier: Topic :: Multimedia :: Video
|
|
|
13
13
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
14
14
|
Requires-Python: >=3.11
|
|
15
15
|
Requires-Dist: openai[realtime]>=1.68.2
|
|
16
|
-
Requires-Dist: videosdk-agents>=0.0.
|
|
16
|
+
Requires-Dist: videosdk-agents>=0.0.21
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
|
|
19
19
|
# VideoSDK OpenAI Plugin
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
videosdk/plugins/openai/__init__.py,sha256=1jbc4HOYxkLeruM9RAqmZYSBdnr74gnPHmCNMKXEPrg,259
|
|
2
|
+
videosdk/plugins/openai/llm.py,sha256=h6xuJmyjg6InL9tr5pKBGt_5bNMpJ4XqnO72OtmCJ0c,7122
|
|
3
|
+
videosdk/plugins/openai/realtime_api.py,sha256=B2RlEV_yK0R4K1dPTyhhPewoa9bzd43ytEfsLKaHUUQ,22554
|
|
4
|
+
videosdk/plugins/openai/stt.py,sha256=YZROX-BjTqtWiT6ouMZacLkMYbmao3emB-88ewN93jg,9492
|
|
5
|
+
videosdk/plugins/openai/tts.py,sha256=o5ktMUzjPkj64L5qqRaKPTWq7Na56TshMnLfU-sK36k,4417
|
|
6
|
+
videosdk/plugins/openai/version.py,sha256=9_nCx08vWHyj8RiwIYqwqah3T4SPB46e0jnaNSxxfDc,22
|
|
7
|
+
videosdk_plugins_openai-0.0.21.dist-info/METADATA,sha256=Docf55C8KnCxCAXOGa6i_UxbuYsLCPNiIyW25EdJEQM,827
|
|
8
|
+
videosdk_plugins_openai-0.0.21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
+
videosdk_plugins_openai-0.0.21.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
videosdk/plugins/openai/__init__.py,sha256=1jbc4HOYxkLeruM9RAqmZYSBdnr74gnPHmCNMKXEPrg,259
|
|
2
|
-
videosdk/plugins/openai/llm.py,sha256=wvWfQ8OA1AcdMMDEf4y93-2vSnSdulYjGpd9IVWFdxc,6145
|
|
3
|
-
videosdk/plugins/openai/realtime_api.py,sha256=B2RlEV_yK0R4K1dPTyhhPewoa9bzd43ytEfsLKaHUUQ,22554
|
|
4
|
-
videosdk/plugins/openai/stt.py,sha256=YZROX-BjTqtWiT6ouMZacLkMYbmao3emB-88ewN93jg,9492
|
|
5
|
-
videosdk/plugins/openai/tts.py,sha256=LDsYXuHBoN-8g1iYt7JV_vRWOJZvhUN8QZQj_q264rU,3635
|
|
6
|
-
videosdk/plugins/openai/version.py,sha256=9OK8yo7gxBYvFxF5sp_Pg19ucyUGzDpUXRaYqvJmYCQ,22
|
|
7
|
-
videosdk_plugins_openai-0.0.19.dist-info/METADATA,sha256=ng3Wo9ut4Iua1rQBNHeDrA7dRupHxjThjvEKMzl7w-g,827
|
|
8
|
-
videosdk_plugins_openai-0.0.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
-
videosdk_plugins_openai-0.0.19.dist-info/RECORD,,
|
|
File without changes
|