Home / Strands ์Œ์„ฑ AI / ๐ŸŽฏ Strands ์Œ์„ฑ AI
Module

๐ŸŽฏ Strands ์Œ์„ฑ AI

Nova Sonic, BidiAgent, WebRTC

โฑ 60๋ถ„ 101 / 189

Strands ์Œ์„ฑ AI

Nova Sonic ยท BidiAgent ยท WebRTC

์—์ด์ „ํŠธ์™€ ๋Œ€ํ™”ํ•œ๋‹ค โ€” ๋ชฉ์†Œ๋ฆฌ๋กœ

Speech-to-Speech ์–‘๋ฐฉํ–ฅ ์Œ์„ฑ ์—์ด์ „ํŠธ โ€” ํ…์ŠคํŠธ ๋ณ€ํ™˜ ์—†๋Š” ์ง์ ‘ ์ฒ˜๋ฆฌ

์Œ์„ฑ AI ๊ฐœ์š”

Speech-to-Speech ยท ํŒŒ์ดํ”„๋ผ์ธ ๋น„๊ต ยท ์•„ํ‚คํ…์ฒ˜

PART 1 ยท ์Œ์„ฑ AI ๊ฐœ์š”

Speech-to-Speech

ํ…์ŠคํŠธ ๋ณ€ํ™˜ ์—†์ด ์Œ์„ฑ์„ ์ง์ ‘ ์ดํ•ดํ•˜๊ณ  ์Œ์„ฑ์œผ๋กœ ์‘๋‹ตํ•˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์ฒ˜๋ฆฌ

Speech-to-Speech

์Œ์„ฑ ์ž…๋ ฅ์„ ๋ชจ๋ธ์ด ์ง์ ‘ ์ดํ•ดํ•˜๊ณ  ์Œ์„ฑ ํ† ํฐ์œผ๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค โ€” End-to-end ๋‹จ์ผ ๋ชจ๋ธ

  • TTFA ํ‰๊ท  ~1.09์ดˆ
  • ๊ฐ์ •ยท์–ต์–‘ ๋“ฑ ํŒŒ๋ผ์–ธ์–ด ์ •๋ณด ๋ณด์กด
  • ๋‹จ์ผ API ํ˜ธ์ถœ๋กœ ์ „์ฒด ์ฒ˜๋ฆฌ ์™„๊ฒฐ
  • WebRTC ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ + ๋„๊ตฌ ๊ฒฐํ•ฉ
takeaway

STT โ†’ LLM โ†’ TTS 3๋‹จ๊ณ„๋Š” ๋ ˆ์ดํ„ด์‹œ๊ฐ€ ๋ˆ„์ ๋˜๊ณ  ํ†คยท๊ฐ์ •์ด ์†Œ์‹ค๋ฉ๋‹ˆ๋‹ค โ€” ๋„ค์ดํ‹ฐ๋ธŒ ์Œ์„ฑ ๋ชจ๋ธ์ด ๋‘ ๋ฌธ์ œ๋ฅผ ๋™์‹œ์— ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

PART 1 ยท ์Œ์„ฑ AI ๊ฐœ์š”

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 ํ˜ธ์ถœ๋กœ ์ „์ฒด ์ฒ˜๋ฆฌ ์™„๊ฒฐ

๋ชจ๋ธ์ด ์˜ค๋””์˜ค ํ† ํฐ์„ ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ์ค‘๊ฐ„ ๋ณ€ํ™˜ ์—†์ด ์Œ์„ฑ์˜ ๋ชจ๋“  ๋‰˜์•™์Šค๋ฅผ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต๋„ ์Œ์„ฑ ํ† ํฐ์œผ๋กœ ์ง์ ‘ ์ƒ์„ฑํ•˜์—ฌ ์ž์—ฐ์Šค๋Ÿฌ์šด ์–ต์–‘๊ณผ ์†๋„๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

PART 1 ยท ์Œ์„ฑ AI ๊ฐœ์š”

Speech-to-Speech ์„ฑ๋Šฅ ์ง€ํ‘œ

TTFA ํ‰๊ท  ~1.09์ดˆ โ€” ๊ธฐ์กด ํŒŒ์ดํ”„๋ผ์ธ ๋Œ€๋น„ ํฌ๊ฒŒ ๋‹จ์ถ•๋œ ์‘๋‹ต ์†๋„

~1.09s TTFA (Time-To-First-Audio) ํ‰๊ท 
10 ์ง€์› ๋กœ์ผ€์ผ ์ˆ˜
24kHz ์ถœ๋ ฅ ์˜ค๋””์˜ค ์ƒ˜ํ”Œ๋ ˆ์ดํŠธ (์ž…๋ ฅ 16kHz LPCM)
PART 1 ยท ์Œ์„ฑ AI ๊ฐœ์š”

์Œ์„ฑ ์—์ด์ „ํŠธ ์•„ํ‚คํ…์ฒ˜

WebRTC ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ ์œ„์— Speech-to-Speech ๋ชจ๋ธ๊ณผ ๋„๊ตฌ๋ฅผ ๊ฒฐํ•ฉ

  1. 1
    ์˜ค๋””์˜ค ์ž…๋ ฅ

    ๋งˆ์ดํฌ์—์„œ 16kHz LPCM ์˜ค๋””์˜ค๋ฅผ ์บก์ฒ˜. WebRTC ๋˜๋Š” WebSocket์„ ํ†ตํ•ด ์„œ๋ฒ„๋กœ ์ŠคํŠธ๋ฆฌ๋ฐ ์ „์†ก.

  2. 2
    Speech-to-Speech ๋ชจ๋ธ

    ์˜ค๋””์˜ค ํ† ํฐ์„ ์ง์ ‘ ์ดํ•ดํ•˜๊ณ  ์ถ”๋ก . ๋„๊ตฌ ํ˜ธ์ถœ์ด ํ•„์š”ํ•˜๋ฉด JSON์œผ๋กœ ์˜๋„๋ฅผ ๋ฐ˜ํ™˜, ์•„๋‹ˆ๋ฉด ๋ฐ”๋กœ ์Œ์„ฑ ํ† ํฐ ์ƒ์„ฑ.

  3. 3
    ๋„๊ตฌ ์‹คํ–‰

    ์—์ด์ „ํ‹ฑ ๋ฃจํ”„๊ฐ€ ๋ชจ๋ธ ๊ฒฐ์ •์— ๋”ฐ๋ผ ์™ธ๋ถ€ ๋„๊ตฌ๋ฅผ ํ˜ธ์ถœ. ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ปจํ…์ŠคํŠธ์— ์ถ”๊ฐ€ํ•˜๊ณ  ๋ชจ๋ธ์— ๋ฐ˜ํ™˜.

  4. 4
    ์˜ค๋””์˜ค ์ถœ๋ ฅ

    ๋ชจ๋ธ์ด ์ƒ์„ฑํ•œ 24kHz LPCM ์Œ์„ฑ ์ฒญํฌ๋ฅผ ์Šคํ”ผ์ปค๋กœ ์‹ค์‹œ๊ฐ„ ์žฌ์ƒ. ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ฒซ ์Œ์ ˆ๋ถ€ํ„ฐ ์ฆ‰์‹œ ์ถœ๋ ฅ.

takeaway

์ž…๋ ฅยท์ถ”๋ก ยท๋„๊ตฌยท์ถœ๋ ฅ์ด ํ•˜๋‚˜์˜ ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆผ ์œ„์—์„œ ์ด์–ด์ ธ ์ฒซ ์Œ์ ˆ๋ถ€ํ„ฐ ์ฆ‰์‹œ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

Nova Sonic

TTFA ํ‰๊ท  ~1.09์ดˆ ยท ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐ ยท ํ„ด ๊ฐ์ง€

PART 2 ยท Nova Sonic

Nova Sonic

Bedrock ๋„ค์ดํ‹ฐ๋ธŒ Speech-to-Speech ๋ชจ๋ธ โ€” ์–‘๋ฐฉํ–ฅ ์‹ค์‹œ๊ฐ„ ์Œ์„ฑ ๋Œ€ํ™”

Amazon Nova Sonic

HTTP/2 ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ ์œ„์—์„œ ์‚ฌ์šฉ์ž ๋ฐœํ™” ์ค‘์—๋„ ์ฒ˜๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” full-duplex ์Œ์„ฑ ๋ชจ๋ธ

  • ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐ โ€” full-duplex
  • ์ž๋™ ํ„ด ๊ฐ์ง€ โ€” VAD ๋‚ด์žฅ
  • 10๊ฐœ ๋กœ์ผ€์ผ โ€” ํ•œ๊ตญ์–ด ๋ฏธ์ง€์›
  • ๋„๊ตฌ ํ˜ธ์ถœ โ€” toolUse ์ด๋ฒคํŠธ
takeaway

์‚ฌ์šฉ์ž๊ฐ€ ๋งํ•˜๋Š” ๋„์ค‘์—๋„ ๋ชจ๋ธ์ด ์ฒ˜๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค โ€” TTFA ํ‰๊ท  ~1.09์ดˆ๋กœ ์‚ฌ๋žŒ ๊ฐ„ ๋Œ€ํ™”์— ๊ฐ€๊นŒ์šด ์‘๋‹ต ์†๋„๋ฅผ ๋ƒ…๋‹ˆ๋‹ค.

PART 2 ยท Nova Sonic

Amazon Nova Sonic ํ•ต์‹ฌ ๊ธฐ๋Šฅ

์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐยท์ž๋™ ํ„ด ๊ฐ์ง€ยท๋‹ค๊ตญ์–ดยท๋„๊ตฌ ํ˜ธ์ถœ โ€” ์‹ค์‹œ๊ฐ„ ๋Œ€ํ™”๋ฅผ ์ง€ํƒฑํ•˜๋Š” 4๊ฐ€์ง€ ๊ธฐ๋Šฅ

์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆฌ๋ฐ

์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์ด ๋™์‹œ์— ํ๋ฅด๋Š” full-duplex ํ†ต์‹  โ€” ๋Š๊น€ ์—†๋Š” ๋Œ€ํ™”

์ž๋™ ํ„ด ๊ฐ์ง€

Voice Activity Detection์œผ๋กœ ๋ฐœํ™” ์‹œ์ž‘ยท์ข…๋ฃŒ๋ฅผ ์ž๋™ ์ธ์‹

๋‹ค๊ตญ์–ด ์ง€์›

10๊ฐœ ๋กœ์ผ€์ผ ์ง€์› โ€” ์˜์–ด, ์ŠคํŽ˜์ธ์–ด, ํ”„๋ž‘์Šค์–ด, ์ผ๋ณธ์–ด ๋“ฑ

๋„๊ตฌ ํ˜ธ์ถœ ํ†ตํ•ฉ

์Œ์„ฑ ๋Œ€ํ™” ์ค‘ ์—์ด์ „ํŠธ ๋„๊ตฌ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์Œ์„ฑ์œผ๋กœ ์ „๋‹ฌ

takeaway

ํ•œ๊ตญ์–ด๋Š” ์•„์ง ๋ฏธ์ง€์›์ž…๋‹ˆ๋‹ค โ€” ํ•œ๊ตญ์–ด ์„œ๋น„์Šค๋Š” ์˜์–ด ๋กœ์ผ€์ผ ์šฐํšŒ ๋˜๋Š” STT+LLM+TTS ๋ณ‘ํ–‰์ด ํ˜„์žฌ์˜ ์„ ํƒ์ง€์ž…๋‹ˆ๋‹ค.

PART 2 ยท Nova Sonic

๋Œ€ํ™” ์žฅ๋ฉด โ€” barge-in์˜ ์ˆœ๊ฐ„

์—์ด์ „ํŠธ๊ฐ€ ๋งํ•˜๋Š” ๋„์ค‘ ์‚ฌ์šฉ์ž๊ฐ€ ๋ผ์–ด๋“ค์–ด๋„ ์ด์–ด์ง€๋Š” ๋Œ€ํ™” โ€” full-duplex ํƒ€์ž„๋ผ์ธ




์‹ค์‹œ๊ฐ„ ๋Œ€ํ™” ํƒ€์ž„๋ผ์ธ โ€” FULL-DUPLEX
0์ดˆ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 8์ดˆ ยท ๋ฐœํ™”๋Š” ์˜์–ด ์˜ˆ์‹œ(ํ•œ๊ตญ์–ด ๋กœ์ผ€์ผ ๋ฏธ์ง€์›)




์‚ฌ์šฉ์ž
๋งˆ์ดํฌ ยท 16kHz LPCM


"Find me a flight to Portland."

"Wait โ€” afternoon only."




์—์ด์ „ํŠธ
์Šคํ”ผ์ปค ยท 24kHz LPCM


"I found three flights. The firstโ€ฆ"

์ฆ‰์‹œ ์ค‘๋‹จ

"Two afternoon flightsโ€ฆ"






VAD ํ„ด ๊ฐ์ง€ โ€” ๋ฐœํ™” ์ข…๋ฃŒ ์ธ์‹
โ”œ TTFA ~1.09s โ”ค
barge-in โ€” ๋ฐœํ™” ์ค‘ ๋ผ์–ด๋“ค๊ธฐ



์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์ด ๋™์‹œ์— ํ๋ฅด๋Š” HTTP/2 ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ โ€” ๋ผ์–ด๋“œ๋Š” ์ˆœ๊ฐ„ VAD๊ฐ€ ์ƒˆ ๋ฐœํ™”๋ฅผ ๊ฐ์ง€ํ•ด ์‘๋‹ต์„ ์ค‘๋‹จํ•˜๊ณ , ์ƒˆ ํ„ด์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. push-to-talk ๋ฒ„ํŠผ์€ ์—†์Šต๋‹ˆ๋‹ค.


PART 2 ยท Nova Sonic

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()์„ ์—ฐ๊ฒฐํ•ด ์–‘๋ฐฉํ–ฅ ์Œ์„ฑ ์„ธ์…˜ ์‹œ์ž‘

์ฝ”๋“œ

python
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()])
PART 2 ยท Nova Sonic

Nova Sonic ์ŠคํŽ™ ๋น„๊ต

๊ฒฝ์Ÿ Speech-to-Speech ๋ชจ๋ธ ๋Œ€๋น„ Nova Sonic์˜ ํฌ์ง€์…”๋‹

ํ•ญ๋ชฉNova SonicGemini LiveOpenAI Realtime
TTFAํ‰๊ท  ~1.09์ดˆ๊ณต์‹ ๋ฏธ๊ณต๊ฐœ๊ณต์‹ ๋ฏธ๊ณต๊ฐœ
์ปจํ…์ŠคํŠธ๊ณต์‹ ๋ฏธ๊ณต๊ฐœ128K (๋„ค์ดํ‹ฐ๋ธŒ ์˜ค๋””์˜ค)32K ํ† ํฐ
ํ„ด ๊ฐ์ง€VAD ๋‚ด์žฅVAD ๋‚ด์žฅVAD + Server VAD
๋กœ์ผ€์ผ10๊ฐœ97๊ฐœ ์–ธ์–ด๊ณต์‹ ๋ฏธ๊ณต๊ฐœ
ํ•œ๊ตญ์–ดโœ— ๋ฏธ์ง€์›โœ“โœ“
๊ณผ๊ธˆํ† ํฐ ๊ธฐ๋ฐ˜ํ† ํฐ ๊ธฐ๋ฐ˜ํ† ํฐ ๊ธฐ๋ฐ˜ (ํ…์ŠคํŠธยท์˜ค๋””์˜ค ํ† ํฐ ๋ณ„๋„ ๋‹จ๊ฐ€)
takeaway

TTFA ๊ณต์‹ ์ˆ˜์น˜๋Š” Nova Sonic๋งŒ ๊ณต๊ฐœ(ํ‰๊ท  ~1.09์ดˆ)๋ผ ์žˆ์Šต๋‹ˆ๋‹ค โ€” ์‹ค์ œ ์„ ํƒ์„ ๊ฐ€๋ฅด๋Š” ๊ฒƒ์€ ๋กœ์ผ€์ผ(ํ•œ๊ตญ์–ด) ์ง€์›ยท๊ณผ๊ธˆ ๋ฐฉ์‹ยท์„ธ์…˜ ์ œํ•œ์ž…๋‹ˆ๋‹ค.

BidiAgent ๊ตฌํ˜„

BidiAudioIO ยท ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ ยท ๋„๊ตฌ ํ†ตํ•ฉ

PART 3 ยท BidiAgent ๊ตฌํ˜„

BidiAgent

BidiNovaSonicModel ยท BidiAudioIO ยท ๋„๊ตฌ โ€” ์–‘๋ฐฉํ–ฅ ์Œ์„ฑ ์—์ด์ „ํŠธ์˜ 3์ธต ๊ตฌ์„ฑ

BidiAgent

์–‘๋ฐฉํ–ฅ ์„ธ์…˜ ์ „์šฉ ์—์ด์ „ํŠธ โ€” ๋„๊ตฌ ํ˜ธ์ถœ ์ค‘์—๋„ ์Œ์„ฑ ์ŠคํŠธ๋ฆผ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค

  • BidiNovaSonicModel โ€” ๋ชจ๋ธ ๋ž˜ํผ
  • BidiAudioIO โ€” ๋งˆ์ดํฌยท์Šคํ”ผ์ปค I/O
  • ์—์ด์ „ํ‹ฑ ๋ฃจํ”„ โ€” ๊ธฐ์กด Strands์™€ ๋™์ผ
  • LPCM ์ž…๋ ฅ 16kHz / ์ถœ๋ ฅ 24kHz
takeaway

๋ชจ๋ธ์ด toolUse๋ฅผ ์š”์ฒญํ•˜๋ฉด ๋ฃจํ”„๊ฐ€ ๋„๊ตฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์Œ์„ฑ ์ŠคํŠธ๋ฆผ์— ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค โ€” ๋Œ€ํ™”๊ฐ€ ๋Š๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

PART 3 ยท BidiAgent ๊ตฌํ˜„

BidiAgent ์ „์ฒด ๊ตฌํ˜„

BidiNovaSonicModel + BidiAudioIO + ๋„๊ตฌ๋ฅผ ๊ฒฐํ•ฉํ•œ ์Œ์„ฑ ์—์ด์ „ํŠธ ์™„์„ฑ ์ฝ”๋“œ

ํ•ต์‹ฌ ํฌ์ธํŠธ

@tool
์Œ์„ฑ ๋Œ€ํ™” ์ค‘ ๋ชจ๋ธ์ด ํ˜ธ์ถœํ•˜๋Š” ๋„๊ตฌ โ€” ํ…์ŠคํŠธ ์—์ด์ „ํŠธ์™€ ๋™์ผํ•œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ
BidiNovaSonicModel
Nova 2 Sonic ๋ชจ๋ธ ID + client_config(region)๋กœ ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ ์—ฐ๊ฒฐ
BidiAgent
๋ชจ๋ธ + ๋„๊ตฌ + system_prompt ์กฐ๋ฆฝ โ€” ์—์ด์ „ํŠธ ๊ตฌ์„ฑ์€ ๊ธฐ์กด๊ณผ ๋™์ผ
await agent.run()
inputsยทoutputs์— ๋งˆ์ดํฌยท์Šคํ”ผ์ปค ์—ฐ๊ฒฐ โ€” asyncio ๊ธฐ๋ฐ˜ ์–‘๋ฐฉํ–ฅ ์„ธ์…˜

์ฝ”๋“œ

python
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())
PART 3 ยท BidiAgent ๊ตฌํ˜„

์–‘๋ฐฉํ–ฅ ์˜ค๋””์˜ค ์ฒ˜๋ฆฌ ํ๋ฆ„

๋งˆ์ดํฌ ์ž…๋ ฅ๋ถ€ํ„ฐ ์Šคํ”ผ์ปค ์ถœ๋ ฅ๊นŒ์ง€ โ€” ์‹ค์‹œ๊ฐ„ ์–‘๋ฐฉํ–ฅ ์˜ค๋””์˜ค ํŒŒ์ดํ”„๋ผ์ธ

  1. 1
    Mic Capture

    ์‹œ์Šคํ…œ ๋งˆ์ดํฌ์—์„œ 16kHz PCM ์˜ค๋””์˜ค๋ฅผ 512ํ”„๋ ˆ์ž„ ๋ฒ„ํผ(๊ธฐ๋ณธ๊ฐ’) ๋‹จ์œ„๋กœ ์บก์ฒ˜. BidiAudioIO๋Š” PyAudio ๊ธฐ๋ฐ˜.

  2. 2
    Audio Event ๋ณ€ํ™˜

    16kHz LPCM ํ”„๋ ˆ์ž„์„ ์˜ค๋””์˜ค ์ž…๋ ฅ ์ด๋ฒคํŠธ๋กœ ๊ฐ์‹ธ ์ „์†ก ํ์— ์ ์žฌ. ์••์ถ• ์—†์ด ์›์‹œ PCM ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ.

  3. 3
    Stream to Model

    HTTP/2 ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ธ์ฝ”๋”ฉ๋œ ์˜ค๋””์˜ค ์ฒญํฌ๋ฅผ Nova Sonic์— ์‹ค์‹œ๊ฐ„ ์ „์†ก. ๋ฐœํ™” ์ค‘์—๋„ ๋ชจ๋ธ์ด ์ฒ˜๋ฆฌ ์‹œ์ž‘.

  4. 4
    Model Response

    ๋ชจ๋ธ์ด ์˜ค๋””์˜ค ํ† ํฐ์œผ๋กœ ์‘๋‹ต์„ ์ƒ์„ฑ. toolUse ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ์—์ด์ „ํ‹ฑ ๋ฃจํ”„๊ฐ€ ๋„๊ตฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜.

  5. 5
    PCM Buffering

    ๋ชจ๋ธ์ด ๋ฐ˜ํ™˜ํ•œ 24kHz LPCM ์˜ค๋””์˜ค ์ฒญํฌ๋ฅผ ๋ฒ„ํผ๋ง. ์ฒญํฌ ๊ฐ„ ๋Š๊น€ ์—†์ด ์—ฐ์†์ ์ธ ์žฌ์ƒ ๋ณด์žฅ.

  6. 6
    Speaker Output

    ๋””์ฝ”๋”ฉ๋œ PCM ์˜ค๋””์˜ค๋ฅผ ์Šคํ”ผ์ปค๋กœ ์‹ค์‹œ๊ฐ„ ์žฌ์ƒ. ์ฒซ ์ฒญํฌ ๋„์ฐฉ ์ฆ‰์‹œ ์žฌ์ƒ ์‹œ์ž‘ํ•˜์—ฌ ์ฒด๊ฐ ๋ ˆ์ดํ„ด์‹œ ์ตœ์†Œํ™”.

takeaway

์บก์ฒ˜๋ถ€ํ„ฐ ์žฌ์ƒ๊นŒ์ง€ ์ „ ๊ตฌ๊ฐ„์ด ์ŠคํŠธ๋ฆฌ๋ฐ์ž…๋‹ˆ๋‹ค โ€” ์ฒซ ์ฒญํฌ ๋„์ฐฉ ์ฆ‰์‹œ ์žฌ์ƒ์„ ์‹œ์ž‘ํ•ด ์ฒด๊ฐ ๋ ˆ์ดํ„ด์‹œ๋ฅผ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.

PART 3 ยท BidiAgent ๊ตฌํ˜„

BidiAgent ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ

์–‘๋ฐฉํ–ฅ ์Œ์„ฑ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” 3๊ฐœ ๋ ˆ์ด์–ด์™€ ์—ญํ•  ๋ถ„๋‹ด

BidiNovaSonicModel

Bedrock Nova 2 Sonic ๋ชจ๋ธ ๋ž˜ํผ โ€” HTTP/2 ์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ ๊ด€๋ฆฌ

BidiAudioIO

๋งˆ์ดํฌ ์ž…๋ ฅ ยท ์Šคํ”ผ์ปค ์ถœ๋ ฅ ยท LPCM ์ŠคํŠธ๋ฆผ์„ ํ†ตํ•ฉํ•˜๋Š” ์˜ค๋””์˜ค I/O ๋ ˆ์ด์–ด

BidiAgent(์—์ด์ „ํ‹ฑ ๋ฃจํ”„)

๋„๊ตฌ ํ˜ธ์ถœ ํŒ๋‹จ ยท ์‹คํ–‰ ยท ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ โ€” ๊ธฐ์กด Strands ๋ฃจํ”„์™€ ๋™์ผ

takeaway

๋ชจ๋ธ ๋ž˜ํผ ยท ์˜ค๋””์˜ค I/O ยท ์—์ด์ „ํ‹ฑ ๋ฃจํ”„ โ€” ์„ธ ๋ ˆ์ด์–ด์˜ ์—ญํ•  ๋ถ„๋‹ด์ด ์–‘๋ฐฉํ–ฅ ์Œ์„ฑ ์—์ด์ „ํŠธ์˜ ์ „๋ถ€์ž…๋‹ˆ๋‹ค.

๋ฉ€ํ‹ฐ ํ”„๋กœ๋ฐ”์ด๋”

Gemini Live ยท OpenAI Realtime ยท ํ”„๋กœ๋ฐ”์ด๋” ์ „ํ™˜

PART 4 ยท ๋ฉ€ํ‹ฐ ํ”„๋กœ๋ฐ”์ด๋”

๋ฉ€ํ‹ฐ ํ”„๋กœ๋ฐ”์ด๋”

Nova Sonic ยท Gemini Live ยท OpenAI Realtime โ€” ๋™์ผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ „ํ™˜

๋ฉ€ํ‹ฐ ํ”„๋กœ๋ฐ”์ด๋”

๋ชจ๋ธ ํด๋ž˜์Šค๋งŒ ๊ต์ฒดํ•˜๋ฉด ๋‚˜๋จธ์ง€ ์ฝ”๋“œ๋Š” ๊ทธ๋Œ€๋กœ โ€” ํ”„๋กœ๋ฐ”์ด๋” ์ „ํ™˜์˜ ์•„ํ‚คํ…์ฒ˜ ๋ณ€ํ™” ์ตœ์†Œํ™”

  • BidiNovaSonicModel โ€” HTTP/2 bidi
  • BidiGeminiLiveModel โ€” WebSocket
  • BidiOpenAIRealtimeModel โ€” WebSocket
  • ๋„๊ตฌ ยท BidiAudioIO โ€” ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉ
takeaway

ํ”„๋กœ๋ฐ”์ด๋”๋งˆ๋‹ค ๋ ˆ์ดํ„ด์‹œยท์–ธ์–ด ์ง€์›ยท๊ฐ์ • ํ‘œํ˜„ ์ˆ˜์ค€์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค โ€” ํ•œ๊ตญ์–ด๊ฐ€ ํ•„์š”ํ•˜๋ฉด Gemini LiveยทOpenAI Realtime์ด ํ˜„์žฌ ์„ ํƒ์ง€์ž…๋‹ˆ๋‹ค.

PART 4 ยท ๋ฉ€ํ‹ฐ ํ”„๋กœ๋ฐ”์ด๋”

๋ฉ€ํ‹ฐ ํ”„๋กœ๋ฐ”์ด๋” ๋น„๊ต

SDK ํด๋ž˜์Šคยทํ”„๋กœํ† ์ฝœยท์ฝ”๋ฑยท์„ธ์…˜ ์ œํ•œ์€ ์ƒ์ด โ€” Strands ํ†ตํ•ฉ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์…‹ ๋ชจ๋‘ ๋™์ผ(์‹คํ—˜์ )

ํ•ญ๋ชฉNova 2 SonicGemini LiveOpenAI Realtime
SDK ํด๋ž˜์ŠคBidiNovaSonicModelBidiGeminiLiveModelBidiOpenAIRealtimeModel
์ „์†ก ํ”„๋กœํ† ์ฝœHTTP/2 bidi streamWebSocketWebSocket
์˜ค๋””์˜ค ์ฝ”๋ฑLPCM16-bit PCM (raw PCM ์ „์šฉ)PCM16 / G.711
์ƒ˜ํ”Œ๋ ˆ์ดํŠธ์ž…๋ ฅ 16kHz / ์ถœ๋ ฅ 24kHz16kHz / 24kHz24kHz
๋„๊ตฌ ํ˜ธ์ถœtoolUse ์ด๋ฒคํŠธfunction_callfunction_call
์„ธ์…˜ ์ œํ•œ์—ฐ๊ฒฐ 8๋ถ„์˜ค๋””์˜ค 15๋ถ„ (์—ฐ๊ฒฐ ~10๋ถ„, ์žฌ๊ฐœ ํ† ํฐ 2์‹œ๊ฐ„)์ตœ๋Œ€ 60๋ถ„
Strands ํ†ตํ•ฉโœ“ (์‹คํ—˜์ )โœ“ (์‹คํ—˜์ )โœ“ (์‹คํ—˜์ )
takeaway

SDK ํด๋ž˜์Šค์™€ ํ”„๋กœํ† ์ฝœยท์ฝ”๋ฑ์€ ๋‹ฌ๋ผ๋„ Strands ํ†ตํ•ฉ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋™์ผํ•ฉ๋‹ˆ๋‹ค โ€” ์…‹ ๋ชจ๋‘ ์•„์ง ์‹คํ—˜์ (experimental) ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

PART 4 ยท ๋ฉ€ํ‹ฐ ํ”„๋กœ๋ฐ”์ด๋”

Gemini Live ์—ฐ๋™

BidiGeminiLiveModel๋กœ ๊ต์ฒด โ€” ๋‚˜๋จธ์ง€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด ํ”„๋กœ๋ฐ”์ด๋” ์ „ํ™˜

ํ•ต์‹ฌ ํฌ์ธํŠธ

BidiGeminiLiveModel
๋ชจ๋ธ ํด๋ž˜์Šค๋งŒ ๊ต์ฒด โ€” Live๋Š” native-audio ๊ณ„์—ด ๋ชจ๋ธ ์‚ฌ์šฉ
client_config(api_key)
ํ”„๋กœ๋ฐ”์ด๋” ์ธ์ฆ โ€” Nova Sonic์˜ region ์ž๋ฆฌ์— API ํ‚ค
BidiAudioIO
์˜ค๋””์˜ค I/O๋Š” ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉ โ€” ๋ณ€๊ฒฝ ์—†์Œ
BidiAgent
๊ตฌ์„ฑ ์ฝ”๋“œ๋Š” Nova Sonic๊ณผ ์™„์ „ ๋™์ผ โ€” ๋„๊ตฌยทํ”„๋กฌํ”„ํŠธ ์œ ์ง€

์ฝ”๋“œ

python
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.",
)
PART 4 ยท ๋ฉ€ํ‹ฐ ํ”„๋กœ๋ฐ”์ด๋”

ํ…์ŠคํŠธ ์—์ด์ „ํŠธ โ†’ ์Œ์„ฑ ์—์ด์ „ํŠธ ์ „ํ™˜

๊ธฐ์กด ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ์—์„œ ์Œ์„ฑ ์—์ด์ „ํŠธ๋กœ ์ „ํ™˜ ์‹œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ

ํ…์ŠคํŠธ ์—์ด์ „ํŠธ ์Œ์„ฑ ์—์ด์ „ํŠธ
๋ชจ๋ธ ํด๋ž˜์Šค BedrockModel
ํ…์ŠคํŠธ ์ž…์ถœ๋ ฅ ์ „์šฉ
BidiNovaSonicModel
HTTP/2 ์–‘๋ฐฉํ–ฅ ์˜ค๋””์˜ค ์ŠคํŠธ๋ฆผ
I/O ๋ ˆ์ด์–ด ํ…์ŠคํŠธ stdin/stdout
๋˜๋Š” REST API
BidiAudioIO
๋งˆ์ดํฌ+์Šคํ”ผ์ปค+LPCM ์ŠคํŠธ๋ฆผ
์‹คํ–‰ ํŒจํ„ด agent("์งˆ๋ฌธ ํ…์ŠคํŠธ")
๋™๊ธฐ ํ˜ธ์ถœ, ๊ฒฐ๊ณผ ํ…์ŠคํŠธ ๋ฐ˜ํ™˜
await agent.run(inputs=..., outputs=...)
๋น„๋™๊ธฐ ์„ธ์…˜, ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆผ
๋„๊ตฌ ์ •์˜ ๋ณ€๊ฒฝ ์—†์Œ
@tool ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๊ทธ๋Œ€๋กœ
๋ณ€๊ฒฝ ์—†์Œ
๋™์ผํ•œ ๋„๊ตฌ๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
์Œ์„ฑ์€ ์—์ด์ „ํŠธ์˜ ๊ฐ€์žฅ ์ž์—ฐ์Šค๋Ÿฌ์šด ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.

Nova Sonic ยท BidiAgent ยท WebRTC โ€” ์Œ์„ฑ์œผ๋กœ ๋Œ€ํ™”ํ•˜๋Š” ์—์ด์ „ํŠธ