๐ฏ Strands ์์ฑ AI
Nova Sonic, BidiAgent, WebRTC
Strands ์์ฑ AI
Nova Sonic ยท BidiAgent ยท WebRTC
์์ด์ ํธ์ ๋ํํ๋ค โ ๋ชฉ์๋ฆฌ๋ก
Speech-to-Speech ์๋ฐฉํฅ ์์ฑ ์์ด์ ํธ โ ํ ์คํธ ๋ณํ ์๋ ์ง์ ์ฒ๋ฆฌ
์์ฑ AI ๊ฐ์
Speech-to-Speech ยท ํ์ดํ๋ผ์ธ ๋น๊ต ยท ์ํคํ ์ฒ
Speech-to-Speech
ํ ์คํธ ๋ณํ ์์ด ์์ฑ์ ์ง์ ์ดํดํ๊ณ ์์ฑ์ผ๋ก ์๋ตํ๋ ๋ค์ดํฐ๋ธ ์ฒ๋ฆฌ
Speech-to-Speech
์์ฑ ์ ๋ ฅ์ ๋ชจ๋ธ์ด ์ง์ ์ดํดํ๊ณ ์์ฑ ํ ํฐ์ผ๋ก ์๋ตํฉ๋๋ค โ End-to-end ๋จ์ผ ๋ชจ๋ธ
- TTFA ํ๊ท ~1.09์ด
- ๊ฐ์ ยท์ต์ ๋ฑ ํ๋ผ์ธ์ด ์ ๋ณด ๋ณด์กด
- ๋จ์ผ API ํธ์ถ๋ก ์ ์ฒด ์ฒ๋ฆฌ ์๊ฒฐ
- WebRTC ์๋ฐฉํฅ ์คํธ๋ฆผ + ๋๊ตฌ ๊ฒฐํฉ
STT โ LLM โ TTS 3๋จ๊ณ๋ ๋ ์ดํด์๊ฐ ๋์ ๋๊ณ ํคยท๊ฐ์ ์ด ์์ค๋ฉ๋๋ค โ ๋ค์ดํฐ๋ธ ์์ฑ ๋ชจ๋ธ์ด ๋ ๋ฌธ์ ๋ฅผ ๋์์ ํด๊ฒฐํฉ๋๋ค.
Speech-to-Speech vs ๊ธฐ์กด ํ์ดํ๋ผ์ธ
3๋จ๊ณ ๋ณํ์ ๋ ์ดํด์ ๋์ ยท๊ฐ์ ์์ค vs ๋จ์ผ ๋ชจ๋ธ์ ์ง์ ์ฒ๋ฆฌ โ ๋ ๋ฐฉ์์ ๊ตฌ์กฐ์ ์ฐจ์ด
STT โ LLM โ TTS
๊ธฐ์กด 3๋จ๊ณ ํ์ดํ๋ผ์ธ
- ์์ฑ โ ํ ์คํธ ๋ณํ(STT) โ LLM ์ถ๋ก โ ํ ์คํธ โ ์์ฑ ํฉ์ฑ(TTS)
- ๊ฐ ๋จ๊ณ๋ง๋ค ๋ ์ดํด์๊ฐ ์ ์ด ๋์ (OpenAI ๊ตฌ Voice Mode ๊ณตํ ํ๊ท 2.8~5.4์ด)
- ๋น์ธ์ด์ ์ ๋ณด(ํค, ๊ฐ์ , ์ต์) ์์ค
- ๊ฐ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ๋ณ ๊ด๋ฆฌยท๋น์ฉ ๋ถ๋ฆฌ ํ์
STT๊ฐ ์์ฑ์ ํ ์คํธ๋ก ๋ณํํ๋ฉด์ ๊ฐ์ ยทํค ์ ๋ณด๋ฅผ ๋ฒ๋ฆฝ๋๋ค. LLM์ ํ ์คํธ๋ง ๋ณด๊ณ ์ถ๋ก ํ๋ฏ๋ก "ํ๋ ๋ชฉ์๋ฆฌ๋ก ๋ถ๋ง ์ ์"์ "์ฐจ๋ถํ ์ง๋ฌธ"์ ๊ตฌ๋ถํ ์ ์์ต๋๋ค.
Speech-to-Speech
๋ค์ดํฐ๋ธ ์์ฑ ๋ชจ๋ธ
- ์์ฑ ์ ๋ ฅ โ ๋ชจ๋ธ์ด ์ง์ ์ดํด โ ์์ฑ ์ถ๋ ฅ
- End-to-end ๋จ์ผ ๋ชจ๋ธ โ TTFA ํ๊ท ~1.09์ด
- ๊ฐ์ ยท์ต์ยท์๋ ๋ฑ ํ๋ผ์ธ์ด ์ ๋ณด ๋ณด์กด
- ๋จ์ผ API ํธ์ถ๋ก ์ ์ฒด ์ฒ๋ฆฌ ์๊ฒฐ
๋ชจ๋ธ์ด ์ค๋์ค ํ ํฐ์ ์ง์ ์ฒ๋ฆฌํ๋ฏ๋ก ์ค๊ฐ ๋ณํ ์์ด ์์ฑ์ ๋ชจ๋ ๋์์ค๋ฅผ ์ดํดํฉ๋๋ค. ์๋ต๋ ์์ฑ ํ ํฐ์ผ๋ก ์ง์ ์์ฑํ์ฌ ์์ฐ์ค๋ฌ์ด ์ต์๊ณผ ์๋๋ฅผ ์ ์ดํฉ๋๋ค.
Speech-to-Speech ์ฑ๋ฅ ์งํ
TTFA ํ๊ท ~1.09์ด โ ๊ธฐ์กด ํ์ดํ๋ผ์ธ ๋๋น ํฌ๊ฒ ๋จ์ถ๋ ์๋ต ์๋
์์ฑ ์์ด์ ํธ ์ํคํ ์ฒ
WebRTC ์๋ฐฉํฅ ์คํธ๋ฆผ ์์ Speech-to-Speech ๋ชจ๋ธ๊ณผ ๋๊ตฌ๋ฅผ ๊ฒฐํฉ
-
1
์ค๋์ค ์ ๋ ฅ
๋ง์ดํฌ์์ 16kHz LPCM ์ค๋์ค๋ฅผ ์บก์ฒ. WebRTC ๋๋ WebSocket์ ํตํด ์๋ฒ๋ก ์คํธ๋ฆฌ๋ฐ ์ ์ก.
-
2
Speech-to-Speech ๋ชจ๋ธ
์ค๋์ค ํ ํฐ์ ์ง์ ์ดํดํ๊ณ ์ถ๋ก . ๋๊ตฌ ํธ์ถ์ด ํ์ํ๋ฉด JSON์ผ๋ก ์๋๋ฅผ ๋ฐํ, ์๋๋ฉด ๋ฐ๋ก ์์ฑ ํ ํฐ ์์ฑ.
-
3
๋๊ตฌ ์คํ
์์ด์ ํฑ ๋ฃจํ๊ฐ ๋ชจ๋ธ ๊ฒฐ์ ์ ๋ฐ๋ผ ์ธ๋ถ ๋๊ตฌ๋ฅผ ํธ์ถ. ์คํ ๊ฒฐ๊ณผ๋ฅผ ์ปจํ ์คํธ์ ์ถ๊ฐํ๊ณ ๋ชจ๋ธ์ ๋ฐํ.
-
4
์ค๋์ค ์ถ๋ ฅ
๋ชจ๋ธ์ด ์์ฑํ 24kHz LPCM ์์ฑ ์ฒญํฌ๋ฅผ ์คํผ์ปค๋ก ์ค์๊ฐ ์ฌ์. ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ์ฒซ ์์ ๋ถํฐ ์ฆ์ ์ถ๋ ฅ.
์ ๋ ฅยท์ถ๋ก ยท๋๊ตฌยท์ถ๋ ฅ์ด ํ๋์ ์ค์๊ฐ ์คํธ๋ฆผ ์์์ ์ด์ด์ ธ ์ฒซ ์์ ๋ถํฐ ์ฆ์ ์ถ๋ ฅ๋ฉ๋๋ค.
Nova Sonic
TTFA ํ๊ท ~1.09์ด ยท ์๋ฐฉํฅ ์คํธ๋ฆฌ๋ฐ ยท ํด ๊ฐ์ง
Nova Sonic
Bedrock ๋ค์ดํฐ๋ธ Speech-to-Speech ๋ชจ๋ธ โ ์๋ฐฉํฅ ์ค์๊ฐ ์์ฑ ๋ํ
Amazon Nova Sonic
HTTP/2 ์๋ฐฉํฅ ์คํธ๋ฆผ ์์์ ์ฌ์ฉ์ ๋ฐํ ์ค์๋ ์ฒ๋ฆฌ๋ฅผ ์์ํ๋ full-duplex ์์ฑ ๋ชจ๋ธ
- ์๋ฐฉํฅ ์คํธ๋ฆฌ๋ฐ โ full-duplex
- ์๋ ํด ๊ฐ์ง โ VAD ๋ด์ฅ
- 10๊ฐ ๋ก์ผ์ผ โ ํ๊ตญ์ด ๋ฏธ์ง์
- ๋๊ตฌ ํธ์ถ โ toolUse ์ด๋ฒคํธ
์ฌ์ฉ์๊ฐ ๋งํ๋ ๋์ค์๋ ๋ชจ๋ธ์ด ์ฒ๋ฆฌ๋ฅผ ์์ํฉ๋๋ค โ TTFA ํ๊ท ~1.09์ด๋ก ์ฌ๋ ๊ฐ ๋ํ์ ๊ฐ๊น์ด ์๋ต ์๋๋ฅผ ๋ ๋๋ค.
Amazon Nova Sonic ํต์ฌ ๊ธฐ๋ฅ
์๋ฐฉํฅ ์คํธ๋ฆฌ๋ฐยท์๋ ํด ๊ฐ์งยท๋ค๊ตญ์ดยท๋๊ตฌ ํธ์ถ โ ์ค์๊ฐ ๋ํ๋ฅผ ์งํฑํ๋ 4๊ฐ์ง ๊ธฐ๋ฅ
์๋ฐฉํฅ ์คํธ๋ฆฌ๋ฐ
์ ๋ ฅ๊ณผ ์ถ๋ ฅ์ด ๋์์ ํ๋ฅด๋ full-duplex ํต์ โ ๋๊น ์๋ ๋ํ
์๋ ํด ๊ฐ์ง
Voice Activity Detection์ผ๋ก ๋ฐํ ์์ยท์ข ๋ฃ๋ฅผ ์๋ ์ธ์
๋ค๊ตญ์ด ์ง์
10๊ฐ ๋ก์ผ์ผ ์ง์ โ ์์ด, ์คํ์ธ์ด, ํ๋์ค์ด, ์ผ๋ณธ์ด ๋ฑ
๋๊ตฌ ํธ์ถ ํตํฉ
์์ฑ ๋ํ ์ค ์์ด์ ํธ ๋๊ตฌ๋ฅผ ํธ์ถํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์์ฑ์ผ๋ก ์ ๋ฌ
ํ๊ตญ์ด๋ ์์ง ๋ฏธ์ง์์ ๋๋ค โ ํ๊ตญ์ด ์๋น์ค๋ ์์ด ๋ก์ผ์ผ ์ฐํ ๋๋ STT+LLM+TTS ๋ณํ์ด ํ์ฌ์ ์ ํ์ง์ ๋๋ค.
๋ํ ์ฅ๋ฉด โ barge-in์ ์๊ฐ
์์ด์ ํธ๊ฐ ๋งํ๋ ๋์ค ์ฌ์ฉ์๊ฐ ๋ผ์ด๋ค์ด๋ ์ด์ด์ง๋ ๋ํ โ full-duplex ํ์๋ผ์ธ
์ค์๊ฐ ๋ํ ํ์๋ผ์ธ โ FULL-DUPLEX
0์ด โโโโโโโโโโโโ 8์ด ยท ๋ฐํ๋ ์์ด ์์(ํ๊ตญ์ด ๋ก์ผ์ผ ๋ฏธ์ง์)
๋ง์ดํฌ ยท 16kHz LPCM
์คํผ์ปค ยท 24kHz LPCM
VAD ํด ๊ฐ์ง โ ๋ฐํ ์ข ๋ฃ ์ธ์
โ TTFA ~1.09s โค
barge-in โ ๋ฐํ ์ค ๋ผ์ด๋ค๊ธฐ
BidiNovaSonicModel ์ด๊ธฐํ
Strands SDK์์ Nova Sonic ๋ชจ๋ธ์ ์๋ฐฉํฅ ์คํธ๋ฆฌ๋ฐ ๋ชจ๋๋ก ์ฐ๊ฒฐ
ํต์ฌ ํฌ์ธํธ
- BidiNovaSonicModel
- model_id์ client_config(region)๋ก ์ด๊ธฐํ โ Nova 2 Sonic ์๋ฐฉํฅ ์ฐ๊ฒฐ
- BidiAudioIO()
- ๋ง์ดํฌ+์คํผ์ปค ํตํฉ I/O โ ์ค๋์ค ํฌ๋งท์ ๋ชจ๋ธ ์ค์ ์ด ๊ฒฐ์ (LPCM)
- BidiAgent(model=, tools=)
- ์๋ฐฉํฅ ์ธ์ ์ ์ฉ ์์ด์ ํธ โ ๋๊ตฌ๋ ๊ธฐ์กด ๋ฐฉ์ ๊ทธ๋๋ก ์ฅ์ฐฉ
- agent.run(inputs=, outputs=)
- audio_io.input()ยทoutput()์ ์ฐ๊ฒฐํด ์๋ฐฉํฅ ์์ฑ ์ธ์ ์์
์ฝ๋
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiNovaSonicModel
# Nova Sonic ์๋ฐฉํฅ ๋ชจ๋ธ ์ด๊ธฐํ
model = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
client_config={"region": "us-east-1"},
)
audio_io = BidiAudioIO() # ๋ง์ดํฌ + ์คํผ์ปค โ ํฌ๋งท์ ๋ชจ๋ธ ์ค์ ์ด ๊ฒฐ์ (LPCM)
# BidiAgent ๊ตฌ์ฑ
agent = BidiAgent(
model=model,
tools=[get_weather, search_db],
)
# ์คํ โ await agent.run(inputs=[audio_io.input()], outputs=[audio_io.output()])
Nova Sonic ์คํ ๋น๊ต
๊ฒฝ์ Speech-to-Speech ๋ชจ๋ธ ๋๋น Nova Sonic์ ํฌ์ง์ ๋
| ํญ๋ชฉ | Nova Sonic | Gemini Live | OpenAI Realtime |
|---|---|---|---|
| TTFA | ํ๊ท ~1.09์ด | ๊ณต์ ๋ฏธ๊ณต๊ฐ | ๊ณต์ ๋ฏธ๊ณต๊ฐ |
| ์ปจํ ์คํธ | ๊ณต์ ๋ฏธ๊ณต๊ฐ | 128K (๋ค์ดํฐ๋ธ ์ค๋์ค) | 32K ํ ํฐ |
| ํด ๊ฐ์ง | VAD ๋ด์ฅ | VAD ๋ด์ฅ | VAD + Server VAD |
| ๋ก์ผ์ผ | 10๊ฐ | 97๊ฐ ์ธ์ด | ๊ณต์ ๋ฏธ๊ณต๊ฐ |
| ํ๊ตญ์ด | โ ๋ฏธ์ง์ | โ | โ |
| ๊ณผ๊ธ | ํ ํฐ ๊ธฐ๋ฐ | ํ ํฐ ๊ธฐ๋ฐ | ํ ํฐ ๊ธฐ๋ฐ (ํ ์คํธยท์ค๋์ค ํ ํฐ ๋ณ๋ ๋จ๊ฐ) |
TTFA ๊ณต์ ์์น๋ Nova Sonic๋ง ๊ณต๊ฐ(ํ๊ท ~1.09์ด)๋ผ ์์ต๋๋ค โ ์ค์ ์ ํ์ ๊ฐ๋ฅด๋ ๊ฒ์ ๋ก์ผ์ผ(ํ๊ตญ์ด) ์ง์ยท๊ณผ๊ธ ๋ฐฉ์ยท์ธ์ ์ ํ์ ๋๋ค.
BidiAgent ๊ตฌํ
BidiAudioIO ยท ์๋ฐฉํฅ ์คํธ๋ฆผ ยท ๋๊ตฌ ํตํฉ
BidiAgent
BidiNovaSonicModel ยท BidiAudioIO ยท ๋๊ตฌ โ ์๋ฐฉํฅ ์์ฑ ์์ด์ ํธ์ 3์ธต ๊ตฌ์ฑ
BidiAgent
์๋ฐฉํฅ ์ธ์ ์ ์ฉ ์์ด์ ํธ โ ๋๊ตฌ ํธ์ถ ์ค์๋ ์์ฑ ์คํธ๋ฆผ์ ์ ์งํฉ๋๋ค
- BidiNovaSonicModel โ ๋ชจ๋ธ ๋ํผ
- BidiAudioIO โ ๋ง์ดํฌยท์คํผ์ปค I/O
- ์์ด์ ํฑ ๋ฃจํ โ ๊ธฐ์กด Strands์ ๋์ผ
- LPCM ์ ๋ ฅ 16kHz / ์ถ๋ ฅ 24kHz
๋ชจ๋ธ์ด toolUse๋ฅผ ์์ฒญํ๋ฉด ๋ฃจํ๊ฐ ๋๊ตฌ๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์์ฑ ์คํธ๋ฆผ์ ์ฃผ์ ํฉ๋๋ค โ ๋ํ๊ฐ ๋๊ธฐ์ง ์์ต๋๋ค.
BidiAgent ์ ์ฒด ๊ตฌํ
BidiNovaSonicModel + BidiAudioIO + ๋๊ตฌ๋ฅผ ๊ฒฐํฉํ ์์ฑ ์์ด์ ํธ ์์ฑ ์ฝ๋
ํต์ฌ ํฌ์ธํธ
- @tool
- ์์ฑ ๋ํ ์ค ๋ชจ๋ธ์ด ํธ์ถํ๋ ๋๊ตฌ โ ํ ์คํธ ์์ด์ ํธ์ ๋์ผํ ๋ฐ์ฝ๋ ์ดํฐ
- BidiNovaSonicModel
- Nova 2 Sonic ๋ชจ๋ธ ID + client_config(region)๋ก ์๋ฐฉํฅ ์คํธ๋ฆผ ์ฐ๊ฒฐ
- BidiAgent
- ๋ชจ๋ธ + ๋๊ตฌ + system_prompt ์กฐ๋ฆฝ โ ์์ด์ ํธ ๊ตฌ์ฑ์ ๊ธฐ์กด๊ณผ ๋์ผ
- await agent.run()
- inputsยทoutputs์ ๋ง์ดํฌยท์คํผ์ปค ์ฐ๊ฒฐ โ asyncio ๊ธฐ๋ฐ ์๋ฐฉํฅ ์ธ์
์ฝ๋
import asyncio
from strands import tool
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiNovaSonicModel
@tool
def get_weather(city: str) -> dict:
"""๋์์ ํ์ฌ ๋ ์จ๋ฅผ ์กฐํํฉ๋๋ค."""
return {"city": city, "temp": 22, "condition": "sunny"}
async def main():
model = BidiNovaSonicModel(model_id="amazon.nova-2-sonic-v1:0",
client_config={"region": "us-east-1"})
agent = BidiAgent(model=model, tools=[get_weather],
system_prompt="You are a helpful voice assistant.")
audio_io = BidiAudioIO() # ๋ง์ดํฌ ์
๋ ฅ ยท ์คํผ์ปค ์ถ๋ ฅ
await agent.run(inputs=[audio_io.input()], outputs=[audio_io.output()])
asyncio.run(main())
์๋ฐฉํฅ ์ค๋์ค ์ฒ๋ฆฌ ํ๋ฆ
๋ง์ดํฌ ์ ๋ ฅ๋ถํฐ ์คํผ์ปค ์ถ๋ ฅ๊น์ง โ ์ค์๊ฐ ์๋ฐฉํฅ ์ค๋์ค ํ์ดํ๋ผ์ธ
-
1
Mic Capture
์์คํ ๋ง์ดํฌ์์ 16kHz PCM ์ค๋์ค๋ฅผ 512ํ๋ ์ ๋ฒํผ(๊ธฐ๋ณธ๊ฐ) ๋จ์๋ก ์บก์ฒ. BidiAudioIO๋ PyAudio ๊ธฐ๋ฐ.
-
2
Audio Event ๋ณํ
16kHz LPCM ํ๋ ์์ ์ค๋์ค ์ ๋ ฅ ์ด๋ฒคํธ๋ก ๊ฐ์ธ ์ ์ก ํ์ ์ ์ฌ. ์์ถ ์์ด ์์ PCM ๊ทธ๋๋ก ์ ๋ฌ.
-
3
Stream to Model
HTTP/2 ์๋ฐฉํฅ ์คํธ๋ฆผ์ผ๋ก ์ธ์ฝ๋ฉ๋ ์ค๋์ค ์ฒญํฌ๋ฅผ Nova Sonic์ ์ค์๊ฐ ์ ์ก. ๋ฐํ ์ค์๋ ๋ชจ๋ธ์ด ์ฒ๋ฆฌ ์์.
-
4
Model Response
๋ชจ๋ธ์ด ์ค๋์ค ํ ํฐ์ผ๋ก ์๋ต์ ์์ฑ. toolUse ์ด๋ฒคํธ ๋ฐ์ ์ ์์ด์ ํฑ ๋ฃจํ๊ฐ ๋๊ตฌ๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ ๋ฐํ.
-
5
PCM Buffering
๋ชจ๋ธ์ด ๋ฐํํ 24kHz LPCM ์ค๋์ค ์ฒญํฌ๋ฅผ ๋ฒํผ๋ง. ์ฒญํฌ ๊ฐ ๋๊น ์์ด ์ฐ์์ ์ธ ์ฌ์ ๋ณด์ฅ.
-
6
Speaker Output
๋์ฝ๋ฉ๋ PCM ์ค๋์ค๋ฅผ ์คํผ์ปค๋ก ์ค์๊ฐ ์ฌ์. ์ฒซ ์ฒญํฌ ๋์ฐฉ ์ฆ์ ์ฌ์ ์์ํ์ฌ ์ฒด๊ฐ ๋ ์ดํด์ ์ต์ํ.
์บก์ฒ๋ถํฐ ์ฌ์๊น์ง ์ ๊ตฌ๊ฐ์ด ์คํธ๋ฆฌ๋ฐ์ ๋๋ค โ ์ฒซ ์ฒญํฌ ๋์ฐฉ ์ฆ์ ์ฌ์์ ์์ํด ์ฒด๊ฐ ๋ ์ดํด์๋ฅผ ์ต์ํํฉ๋๋ค.
BidiAgent ํต์ฌ ์ปดํฌ๋ํธ
์๋ฐฉํฅ ์์ฑ ์์ด์ ํธ๋ฅผ ๊ตฌ์ฑํ๋ 3๊ฐ ๋ ์ด์ด์ ์ญํ ๋ถ๋ด
BidiNovaSonicModel
Bedrock Nova 2 Sonic ๋ชจ๋ธ ๋ํผ โ HTTP/2 ์๋ฐฉํฅ ์คํธ๋ฆผ ๊ด๋ฆฌ
BidiAudioIO
๋ง์ดํฌ ์ ๋ ฅ ยท ์คํผ์ปค ์ถ๋ ฅ ยท LPCM ์คํธ๋ฆผ์ ํตํฉํ๋ ์ค๋์ค I/O ๋ ์ด์ด
BidiAgent(์์ด์ ํฑ ๋ฃจํ)
๋๊ตฌ ํธ์ถ ํ๋จ ยท ์คํ ยท ๊ฒฐ๊ณผ ๋ฐํ โ ๊ธฐ์กด Strands ๋ฃจํ์ ๋์ผ
๋ชจ๋ธ ๋ํผ ยท ์ค๋์ค I/O ยท ์์ด์ ํฑ ๋ฃจํ โ ์ธ ๋ ์ด์ด์ ์ญํ ๋ถ๋ด์ด ์๋ฐฉํฅ ์์ฑ ์์ด์ ํธ์ ์ ๋ถ์ ๋๋ค.
๋ฉํฐ ํ๋ก๋ฐ์ด๋
Gemini Live ยท OpenAI Realtime ยท ํ๋ก๋ฐ์ด๋ ์ ํ
๋ฉํฐ ํ๋ก๋ฐ์ด๋
Nova Sonic ยท Gemini Live ยท OpenAI Realtime โ ๋์ผ ์ธํฐํ์ด์ค๋ก ์ ํ
๋ฉํฐ ํ๋ก๋ฐ์ด๋
๋ชจ๋ธ ํด๋์ค๋ง ๊ต์ฒดํ๋ฉด ๋๋จธ์ง ์ฝ๋๋ ๊ทธ๋๋ก โ ํ๋ก๋ฐ์ด๋ ์ ํ์ ์ํคํ ์ฒ ๋ณํ ์ต์ํ
- BidiNovaSonicModel โ HTTP/2 bidi
- BidiGeminiLiveModel โ WebSocket
- BidiOpenAIRealtimeModel โ WebSocket
- ๋๊ตฌ ยท BidiAudioIO โ ๊ทธ๋๋ก ์ฌ์ฌ์ฉ
ํ๋ก๋ฐ์ด๋๋ง๋ค ๋ ์ดํด์ยท์ธ์ด ์ง์ยท๊ฐ์ ํํ ์์ค์ด ๋ค๋ฆ ๋๋ค โ ํ๊ตญ์ด๊ฐ ํ์ํ๋ฉด Gemini LiveยทOpenAI Realtime์ด ํ์ฌ ์ ํ์ง์ ๋๋ค.
๋ฉํฐ ํ๋ก๋ฐ์ด๋ ๋น๊ต
SDK ํด๋์คยทํ๋กํ ์ฝยท์ฝ๋ฑยท์ธ์ ์ ํ์ ์์ด โ Strands ํตํฉ ์ธํฐํ์ด์ค๋ ์ ๋ชจ๋ ๋์ผ(์คํ์ )
| ํญ๋ชฉ | Nova 2 Sonic | Gemini Live | OpenAI Realtime |
|---|---|---|---|
| SDK ํด๋์ค | BidiNovaSonicModel | BidiGeminiLiveModel | BidiOpenAIRealtimeModel |
| ์ ์ก ํ๋กํ ์ฝ | HTTP/2 bidi stream | WebSocket | WebSocket |
| ์ค๋์ค ์ฝ๋ฑ | LPCM | 16-bit PCM (raw PCM ์ ์ฉ) | PCM16 / G.711 |
| ์ํ๋ ์ดํธ | ์ ๋ ฅ 16kHz / ์ถ๋ ฅ 24kHz | 16kHz / 24kHz | 24kHz |
| ๋๊ตฌ ํธ์ถ | toolUse ์ด๋ฒคํธ | function_call | function_call |
| ์ธ์ ์ ํ | ์ฐ๊ฒฐ 8๋ถ | ์ค๋์ค 15๋ถ (์ฐ๊ฒฐ ~10๋ถ, ์ฌ๊ฐ ํ ํฐ 2์๊ฐ) | ์ต๋ 60๋ถ |
| Strands ํตํฉ | โ (์คํ์ ) | โ (์คํ์ ) | โ (์คํ์ ) |
SDK ํด๋์ค์ ํ๋กํ ์ฝยท์ฝ๋ฑ์ ๋ฌ๋ผ๋ Strands ํตํฉ ์ธํฐํ์ด์ค๋ ๋์ผํฉ๋๋ค โ ์ ๋ชจ๋ ์์ง ์คํ์ (experimental) ๋จ๊ณ์ ๋๋ค.
Gemini Live ์ฐ๋
BidiGeminiLiveModel๋ก ๊ต์ฒด โ ๋๋จธ์ง ์ฝ๋ ๋ณ๊ฒฝ ์์ด ํ๋ก๋ฐ์ด๋ ์ ํ
ํต์ฌ ํฌ์ธํธ
- BidiGeminiLiveModel
- ๋ชจ๋ธ ํด๋์ค๋ง ๊ต์ฒด โ Live๋ native-audio ๊ณ์ด ๋ชจ๋ธ ์ฌ์ฉ
- client_config(api_key)
- ํ๋ก๋ฐ์ด๋ ์ธ์ฆ โ Nova Sonic์ region ์๋ฆฌ์ API ํค
- BidiAudioIO
- ์ค๋์ค I/O๋ ๊ทธ๋๋ก ์ฌ์ฌ์ฉ โ ๋ณ๊ฒฝ ์์
- BidiAgent
- ๊ตฌ์ฑ ์ฝ๋๋ Nova Sonic๊ณผ ์์ ๋์ผ โ ๋๊ตฌยทํ๋กฌํํธ ์ ์ง
์ฝ๋
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiGeminiLiveModel
# Gemini Live ๋ชจ๋ธ๋ก ๊ต์ฒด โ ์ธํฐํ์ด์ค ๋์ผ (Live๋ native-audio ๊ณ์ด)
model = BidiGeminiLiveModel(
model_id="gemini-2.5-flash-native-audio-preview-09-2025",
client_config={"api_key": "GEMINI_API_KEY"},
)
audio_io = BidiAudioIO() # ์ค๋์ค I/O๋ ๊ทธ๋๋ก ์ฌ์ฌ์ฉ
# BidiAgent ์ฝ๋๋ Nova Sonic๊ณผ ์์ ๋์ผ
agent = BidiAgent(
model=model,
tools=[get_weather, search_db],
system_prompt="You are a helpful voice assistant.",
)
ํ ์คํธ ์์ด์ ํธ โ ์์ฑ ์์ด์ ํธ ์ ํ
๊ธฐ์กด ํ ์คํธ ๊ธฐ๋ฐ ์์ด์ ํธ์์ ์์ฑ ์์ด์ ํธ๋ก ์ ํ ์ ๋ณ๊ฒฝ ์ฌํญ
ํ ์คํธ ์ ์ถ๋ ฅ ์ ์ฉ โ BidiNovaSonicModel
HTTP/2 ์๋ฐฉํฅ ์ค๋์ค ์คํธ๋ฆผ
๋๋ REST API โ BidiAudioIO
๋ง์ดํฌ+์คํผ์ปค+LPCM ์คํธ๋ฆผ
๋๊ธฐ ํธ์ถ, ๊ฒฐ๊ณผ ํ ์คํธ ๋ฐํ โ await agent.run(inputs=..., outputs=...)
๋น๋๊ธฐ ์ธ์ , ์ค์๊ฐ ์คํธ๋ฆผ
@tool ๋ฐ์ฝ๋ ์ดํฐ ๊ทธ๋๋ก โ ๋ณ๊ฒฝ ์์
๋์ผํ ๋๊ตฌ๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉ
Nova Sonic ยท BidiAgent ยท WebRTC โ ์์ฑ์ผ๋ก ๋ํํ๋ ์์ด์ ํธ