Skip to content

Commit 4d3a7b8

Browse files
committed
updating speech to speech plugin
1 parent 5b2ba1a commit 4d3a7b8

6 files changed

Lines changed: 30 additions & 24 deletions

File tree

examples/env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ ELEVENLABS_VOICE_ID=voice_id_to_use
1313
# OpenAI API credentials
1414
OPENAI_API_KEY=your_openai_api_key_here
1515
OPENAI_MODEL=model_to_use
16+
OPENAI_REALTIME_MODEL=gpt-4o-realtime-preview

examples/openai_realtime_speech_to_speech/main.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from getstream import Stream
88
from getstream.models import StartClosedCaptionsResponse
99
from getstream.plugins.sts.openai_realtime import OpenAIRealtime
10-
from dataclasses import asdict
11-
import json
1210

1311

1412
logging.basicConfig(
@@ -26,7 +24,6 @@ async def main():
2624

2725
load_dotenv(os.path.join(os.path.dirname(__file__), "..", ".env"))
2826

29-
# Initialize Stream client from env vars (STREAM_API_KEY / SECRET / BASE_URL)
3027
client = Stream.from_env()
3128

3229
user_id = f"user-{uuid4()}"
@@ -52,15 +49,14 @@ async def main():
5249

5350
sts_bot = OpenAIRealtime(
5451
api_key=os.getenv("OPENAI_API_KEY"),
55-
model="gpt-4o-realtime-preview",
52+
model=os.getenv("OPENAI_REALTIME_MODEL"),
5653
instructions="You are a friendly assistant; reply verbally in a short sentence.",
5754
voice="alloy",
5855
)
5956

6057
try:
6158
logging.info("Connecting to OpenAI Realtime...")
6259

63-
# Check if API key is set
6460
if not os.getenv("OPENAI_API_KEY"):
6561
logging.error("❌ OPENAI_API_KEY not found in environment")
6662
return
@@ -88,6 +84,8 @@ async def main():
8884
},
8985
tools=tools,
9086
)
87+
88+
await sts_bot.send_user_message("Give a short greeting to the user.")
9189

9290
logging.info("🎧 Listening for responses... (Press Ctrl+C to stop)")
9391
logging.info("💡 Try speaking in the browser – ask it something like 'start closed captions' to trigger the function call.")
@@ -111,14 +109,10 @@ async def start_closed_captions() -> StartClosedCaptionsResponse:
111109
logging.info("🛠 Assistant requested start_closed_captions()")
112110

113111
result = await start_closed_captions()
114-
115-
# Send the tool result back to the assistant
116112
await sts_bot.send_function_call_output(tool_call_id, result.to_json())
117-
113+
await sts_bot.request_assistant_response()
118114
logging.info("🛠 Replied to tool call with result: %s", result)
119115

120-
121-
122116
except KeyboardInterrupt: # noqa: WPS420
123117
logging.info("\n⏹️ Stopping OpenAI Realtime Speech to Speech bot…")
124118
except Exception as e: # noqa: BLE001

getstream/plugins/sts/openai_realtime/sts.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,13 @@ async def send_user_message(self, text: str):
180180
],
181181
}
182182
)
183+
await self.request_assistant_response()
184+
185+
async def request_assistant_response(self):
186+
"""Ask OpenAI to generate the next assistant turn."""
187+
if not self._is_connected or not self._connection:
188+
raise RuntimeError("Not connected")
189+
183190
await self._connection.response.create()
184191

185192

getstream/plugins/sts/openai_realtime/tests/pyproject.toml

Lines changed: 0 additions & 9 deletions
This file was deleted.

getstream/plugins/sts/openai_realtime/tests/test_openai_realtime.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ async def test_send_function_call_output(mock_call, mock_connection):
9797
)
9898

9999

100+
@pytest.mark.asyncio
101+
async def test_request_assistant_response(mock_call, mock_connection):
102+
mock_call.connect_openai.return_value = mock_connection # type: ignore[attr-defined]
103+
sts = OpenAIRealtime(api_key="abc")
104+
await sts.connect(mock_call)
105+
106+
await sts.request_assistant_response()
107+
108+
mock_connection.response.create.assert_awaited_once()
109+
110+
100111
@pytest.mark.asyncio
101112
async def test_methods_raise_if_not_connected():
102113
sts = OpenAIRealtime(api_key="abc")
@@ -105,4 +116,6 @@ async def test_methods_raise_if_not_connected():
105116
with pytest.raises(RuntimeError):
106117
await sts.send_user_message("hi")
107118
with pytest.raises(RuntimeError):
108-
await sts.send_function_call_output("id", "out")
119+
await sts.send_function_call_output("id", "out")
120+
with pytest.raises(RuntimeError):
121+
await sts.request_assistant_response()

getstream/video/openai.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,12 @@ def patch_realtime_connect(client):
171171
try:
172172
# First, try to import the AsyncRealtimeConnection class
173173
try:
174-
from openai.resources.beta.realtime.connection import (
174+
from openai.resources.beta.realtime.connection import ( # type: ignore
175175
AsyncRealtimeConnection,
176176
)
177177
except ImportError:
178178
# If that fails, try another possible location
179-
from openai.types.beta.realtime.connection import AsyncRealtimeConnection
179+
from openai.types.beta.realtime.connection import AsyncRealtimeConnection # type: ignore
180180

181181
# Store the original recv method and replace it with our patched version
182182
if not hasattr(AsyncRealtimeConnection, "recv"):
@@ -202,7 +202,7 @@ def patch_realtime_connect(client):
202202
)
203203
except ImportError:
204204
# If that fails, try another possible location
205-
from openai.types.beta.realtime.realtime import (
205+
from openai.types.beta.realtime.realtime import ( # type: ignore
206206
AsyncRealtimeConnectionManager,
207207
)
208208

@@ -251,7 +251,7 @@ def patch_realtime_connect(client):
251251
)
252252
except ImportError:
253253
# If that fails, try another possible location
254-
from openai.types.beta.realtime.realtime import (
254+
from openai.types.beta.realtime.realtime import ( # type: ignore
255255
AsyncRealtimeConnectionManager,
256256
)
257257

0 commit comments

Comments
 (0)