three more theoretical samples
This commit is contained in:
@@ -1,14 +1,15 @@
|
|||||||
|
|
||||||
from dailyai.services.transport.DailyTransport import DailyTransportService
|
from dailyai.services.transport.DailyTransport import DailyTransportService
|
||||||
from dailyai.services.tts.AzureTTSService import AzureTTSService
|
from dailyai.services.tts.AzureTTSService import AzureTTSService
|
||||||
|
|
||||||
|
|
||||||
transport = None
|
transport = None
|
||||||
|
mic = None
|
||||||
tts = None
|
tts = None
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global transport
|
global transport
|
||||||
|
global mic
|
||||||
global tts
|
global tts
|
||||||
|
|
||||||
# create a transport service object using environment variables for
|
# create a transport service object using environment variables for
|
||||||
@@ -28,7 +29,7 @@ def main():
|
|||||||
# chunks of audio to play sequentially. the "mic" object is a handle
|
# chunks of audio to play sequentially. the "mic" object is a handle
|
||||||
# we can use to inspect and control the queue if we need to. in this
|
# we can use to inspect and control the queue if we need to. in this
|
||||||
# case we will pipe into this queue from the tts service
|
# case we will pipe into this queue from the tts service
|
||||||
mic = transport.audio_queue()
|
mic = transport.create_audio_queue()
|
||||||
tts.set_output(mic)
|
tts.set_output(mic)
|
||||||
|
|
||||||
transport.on("error", lambda e: print(e))
|
transport.on("error", lambda e: print(e))
|
||||||
@@ -39,7 +40,7 @@ def main():
|
|||||||
def say_one_thing():
|
def say_one_thing():
|
||||||
# say one thing, then leave
|
# say one thing, then leave
|
||||||
tts.run_tts("hello world")
|
tts.run_tts("hello world")
|
||||||
transport.on("audio-queue-empty", shutdown)
|
mic.on("audio-queue-empty", shutdown)
|
||||||
|
|
||||||
|
|
||||||
def shutdown():
|
def shutdown():
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
from dailyai.services.transport.DailyTransport import DailyTransportService
|
from dailyai.services.transport.DailyTransport import DailyTransportService
|
||||||
from dailyai.services.llm.AzureLLMService import AzureLLMService
|
from dailyai.services.llm.AzureLLMService import AzureLLMService
|
||||||
from dailyai.services.tts.AzureTTSService import AzureTTSService
|
from dailyai.services.tts.AzureTTSService import AzureTTSService
|
||||||
@@ -16,18 +15,8 @@ def main():
|
|||||||
transport = DailyTransportService()
|
transport = DailyTransportService()
|
||||||
llm = AzureLLMService()
|
llm = AzureLLMService()
|
||||||
tts = AzureTTSService()
|
tts = AzureTTSService()
|
||||||
mic = transport.audio_queue()
|
mic = transport.create_audio_queue()
|
||||||
tts.set_output(mic)
|
tts.set_output(mic)
|
||||||
|
|
||||||
# similarly, we can tell the llm to pipe infeference output to our tts
|
|
||||||
# service. the design idea here is that any time we call llm.run_llm()
|
|
||||||
# we are creating a cancelable inference call, and somehow behind the
|
|
||||||
# scenes the full pipeline from the llm to the tts service to the
|
|
||||||
# transport's audio queue is managed in such a way as to be
|
|
||||||
# introspectible and cancelable. also, instead of piping the
|
|
||||||
# output to the tts service directly, we could pipe it to an
|
|
||||||
# adapter object that does chunking or processing before sending
|
|
||||||
# to the tts service.
|
|
||||||
llm.set_output(tts)
|
llm.set_output(tts)
|
||||||
|
|
||||||
transport.on("error", lambda e: print(e))
|
transport.on("error", lambda e: print(e))
|
||||||
|
|||||||
27
src/khk-working/theoretical/03-generate-one-video-frame.py
Normal file
27
src/khk-working/theoretical/03-generate-one-video-frame.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
from dailyai.services.transport.DailyTransport import DailyTransportService
|
||||||
|
from dailyai.services.genimage.AzureDalleService import AzureDalleService
|
||||||
|
|
||||||
|
dalle = None
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global dalle
|
||||||
|
|
||||||
|
transport = DailyTransportService()
|
||||||
|
dalle = AzureDalleService()
|
||||||
|
|
||||||
|
# create_video_queue() could presumably take configuration parameters that
|
||||||
|
# correspond to Daily video settings (resolution, framerate, target
|
||||||
|
# bitrate, etc.)
|
||||||
|
cam = transport.create_video_queue()
|
||||||
|
dalle.set_output(cam)
|
||||||
|
|
||||||
|
transport.on("error", lambda e: print(e))
|
||||||
|
transport.on("joined-meeting", say_one_thing)
|
||||||
|
transport.start()
|
||||||
|
|
||||||
|
|
||||||
|
def say_one_thing():
|
||||||
|
# make one image, send it to the video queue, then just hang out.
|
||||||
|
# for simplicity we have not implemented graceful shutdown :-)
|
||||||
|
dalle.generate_image("an astronaut riding a skateboard")
|
||||||
37
src/khk-working/theoretical/04-say-two-things.py
Normal file
37
src/khk-working/theoretical/04-say-two-things.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from dailyai.services.transport.DailyTransport import DailyTransportService
|
||||||
|
from dailyai.services.llm.AzureLLMService import AzureLLMService
|
||||||
|
from dailyai.services.tts.AzureTTSService import AzureTTSService
|
||||||
|
|
||||||
|
transport = None
|
||||||
|
llm = None
|
||||||
|
tts = None
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global transport
|
||||||
|
global llm
|
||||||
|
global tts
|
||||||
|
|
||||||
|
transport = DailyTransportService()
|
||||||
|
llm = AzureLLMService()
|
||||||
|
tts = AzureTTSService()
|
||||||
|
mic = transport.create_audio_queue()
|
||||||
|
tts.set_output(mic)
|
||||||
|
llm.set_output(tts)
|
||||||
|
|
||||||
|
transport.on("error", lambda e: print(e))
|
||||||
|
transport.on("joined-meeting", say_two_things)
|
||||||
|
transport.start()
|
||||||
|
|
||||||
|
|
||||||
|
def say_two_things():
|
||||||
|
# queue two pieces of speech: one specified as a text literal,
|
||||||
|
# and one generated by an llm
|
||||||
|
tts.run_tts("My friend the LLM is now going to tell a joke about llamas.")
|
||||||
|
llm.run_llm("tell me a joke about llamas")
|
||||||
|
transport.on("audio-queue-empty", shutdown)
|
||||||
|
|
||||||
|
|
||||||
|
def shutdown():
|
||||||
|
transport.stop()
|
||||||
|
tts.close()
|
||||||
101
src/khk-working/theoretical/05-llm-speech-and-images.py
Normal file
101
src/khk-working/theoretical/05-llm-speech-and-images.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
from dailyai.services.transport.DailyTransport import DailyTransportService
|
||||||
|
from dailyai.services.llm.AzureLLMService import AzureLLMService
|
||||||
|
from dailyai.services.tts.AzureTTSService import AzureTTSService
|
||||||
|
from dailyai.services.genimage.AzureDalleService import AzureDalleService
|
||||||
|
from dailyai.services.utils.AudioImageSynchronizedPair import AudioImageSynchronizedPair
|
||||||
|
|
||||||
|
transport = None
|
||||||
|
llm = None
|
||||||
|
tts = None
|
||||||
|
dalle = None
|
||||||
|
mic = None
|
||||||
|
cam = None
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global transport
|
||||||
|
global llm
|
||||||
|
global tts
|
||||||
|
global dalle
|
||||||
|
|
||||||
|
transport = DailyTransportService()
|
||||||
|
llm = AzureLLMService()
|
||||||
|
tts = AzureTTSService()
|
||||||
|
dalle = AzureDalleService()
|
||||||
|
|
||||||
|
# set up mic and cam. but don't wire up automatic output to the mic
|
||||||
|
# and cam from our AI services because we need to manage synchronization
|
||||||
|
# of image/speech pairings
|
||||||
|
mic = transport.create_audio_queue()
|
||||||
|
cam = transport.create_video_queue()
|
||||||
|
|
||||||
|
transport.on("error", lambda e: print(e))
|
||||||
|
transport.on("joined-meeting", narrate_calendar_images)
|
||||||
|
transport.start()
|
||||||
|
|
||||||
|
|
||||||
|
def narrate_calendar_images():
|
||||||
|
# let's loop over the months of the year. for each month name, we will have
|
||||||
|
# our llm generate a description of a nice photograph for that month's page
|
||||||
|
# in a calendar.
|
||||||
|
#
|
||||||
|
# then we'll take the text description and:
|
||||||
|
# 1. turn it into speech that we send into the session as audio
|
||||||
|
# 2. turn it into an image that we send into the session as video
|
||||||
|
# we want the audio and video to be synchronized, so we'll use a helper
|
||||||
|
# class to manage that.
|
||||||
|
#
|
||||||
|
# the first `run_llm()` call defines a lambda to process its output.
|
||||||
|
#
|
||||||
|
# the design idea here is that output can be piped into a function that
|
||||||
|
# takes inference completion text as its argument. *or* output can be
|
||||||
|
# piped into an object that has more options (maybe a callback for streaming
|
||||||
|
# results, or a callback for inference completion, or both).
|
||||||
|
#
|
||||||
|
# note that we might queue up the month outputs out of order, but that's
|
||||||
|
# okay for this demo
|
||||||
|
#
|
||||||
|
for month in ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]:
|
||||||
|
synchronizer = AudioImageSynchronizedPair(
|
||||||
|
audio_output=mic, video_output=cam)
|
||||||
|
llm.run_llm(
|
||||||
|
f""""
|
||||||
|
Describe a nature photograph suitable for use in a calendar,
|
||||||
|
for the month of {month}. Include only the image description
|
||||||
|
with no preamble.
|
||||||
|
""",
|
||||||
|
output=lambda inference_text: (
|
||||||
|
dalle.generate_image(inference_text, output=synchronizer),
|
||||||
|
tts.run_tts(inference_text, output=synchronizer)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# the AudioImageSynchronizedPair class seems useful enough that I've listed
|
||||||
|
# it above as a standard utility we can import. but here's a theoretical
|
||||||
|
# implementation
|
||||||
|
|
||||||
|
class TheoreticalAudioImageSynchronizedPair:
|
||||||
|
def __init__(self, audio_output, video_output):
|
||||||
|
self.audio_output = audio_output
|
||||||
|
self.video_output = video_output
|
||||||
|
self.image = None
|
||||||
|
self.audio = None
|
||||||
|
|
||||||
|
def image_generation_complete(self, image):
|
||||||
|
self.image = image
|
||||||
|
self._maybe_send()
|
||||||
|
|
||||||
|
def tts_complete(self, audio):
|
||||||
|
self.audio = audio
|
||||||
|
self._maybe_send()
|
||||||
|
|
||||||
|
def _maybe_send(self):
|
||||||
|
if self.image is not None and self.audio is not None:
|
||||||
|
self.video_output.queue_frame(self.image)
|
||||||
|
self.audio_output.queue_audio(self.audio)
|
||||||
|
|
||||||
|
|
||||||
|
def shutdown():
|
||||||
|
transport.stop()
|
||||||
|
tts.close()
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
-01 just say one thing and exit
|
-01 just say one thing and exit
|
||||||
-02 llm say one thing and exit
|
-02 llm say one thing and exit
|
||||||
-03 send "still frame" video
|
-03 send "still frame" of video
|
||||||
-04 manual intro utterance and then llm say one thing and exit
|
-04 manual intro utterance and then llm say one thing and exit
|
||||||
-05 queue 10 spoken image prompts and synchronize the audio with the generated image frames
|
-05 generate images for the months of the year, synchronized with their spoken descriptions
|
||||||
-06 chat: llm speak and respond (ignoring transcription input while speaking)
|
-06 chat: llm speak and respond (ignoring transcription input while speaking)
|
||||||
-07 chat: llm speak and respond (interruptible)
|
-07 chat: llm speak and respond (interruptible)
|
||||||
-08 two llms arguing about a topic (in the same process)
|
-08 two llms arguing about a topic (in the same process)
|
||||||
@@ -12,3 +12,4 @@
|
|||||||
-11 06 plus sound effects queued from sound file
|
-11 06 plus sound effects queued from sound file
|
||||||
-12 06 plus background music played through a second "mic" device
|
-12 06 plus background music played through a second "mic" device
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user