<@U084APK40NS> I have build a voice assistant usin...
# ask-ai
m
@millions-hair-24956 I have build a voice assistant using multimodel agent. I use function call to end the call. but problem is I prompt my model to say a goodbye message and end the call.but when the ending a call agent ends the call befor the thank you
g
It seems likely that the issue you're facing is related to the timing of the function call execution, which might be interrupting the agent's speech before it completes the goodbye message. My understanding is that you can address this by introducing a delay before executing the function call to end the call, allowing the agent to finish speaking. You can achieve this by using a
setTimeout
or an equivalent delay mechanism in your code to ensure the agent has enough time to complete the goodbye message before the call is terminated. For example, you can add a delay of a few seconds before calling the function to end the call. Would you like more detailed guidance on implementing this delay? Sources: - LiveKit Slack Discussion 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.
m
can you write a code for this
@millions-hair-24956 can you write a code for this
g
Certainly! Here's an example of how you can introduce a delay before ending the call using a
setTimeout
in a Node.js environment with a MultimodalAgent:
Copy code
const agent = new multimodal.MultimodalAgent({
  model,
  fncCtx: {
    sayingGoodbye: {
      description: 'Call this if you are saying goodbye or bye or something similar to the user',
      parameters: {},
      async execute() {
        console.log('Agent is saying goodbye');

        // Introduce a delay of 3 seconds to allow the agent to finish speaking
        await new Promise(resolve => setTimeout(resolve, 3000));

        try {
          // Disconnect from the room
          await context.room.disconnect();
          console.log('Disconnected from the room.');

          // Remove all participants
          const participants = await roomServiceClient.listParticipants(context.room.name);
          await Promise.all(
            participants.map(async participant => {
              await roomServiceClient.removeParticipant(context.room.name, participant.identity);
              console.log(`Removed participant: ${participant.identity}`);
            }),
          );

          // Delete the room
          await roomServiceClient.deleteRoom(context.room.name);
          console.log('Deleted the room.');

          // Close the session
          session.close();
          console.log('Session closed.');

          // Shutdown the context
          context.shutdown();
          console.log('Context shut down.');
        } catch (error) {
          console.error('Error during disconnection process:', error);
        }

        return '';
      },
    },
  },
});
This code introduces a 3-second delay before executing the disconnection logic, allowing the agent to complete its goodbye message. Let me know if you need further assistance! Sources: - LiveKit Slack Discussion 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.
m
@millions-hair-24956
g
I'm here to help with questions related to Livekit. If you have any questions about Livekit or need assistance with its features, please feel free to ask! If your question is about something else, please provide more details or rephrase your question. 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.
m
@millions-hair-24956 please write it in python please
g
Certainly! Here's how you can implement a delay before ending the call using a MultimodalAgent in Python:
Copy code
import asyncio
from livekit import rtc
from livekit.agents import JobContext, WorkerOptions, cli
from livekit.plugins.openai.realtime import RealtimeModel
from livekit.agents.multimodal import MultimodalAgent

async def entrypoint(ctx: JobContext):
    # Initialize the agent
    agent = MultimodalAgent(
        model=RealtimeModel(
            instructions="You are a helpful voice assistant.",
            voice="alloy",
            temperature=0.8,
            modalities=["text", "audio"],
        )
    )

    try:
        # Connect to the room
        await ctx.connect()
        print(f"Connected to room with job ID: {ctx.job.id}")

        # Start the agent
        session = await agent.start(ctx.room)
        print("Agent started successfully.")

        # Define a function to handle the goodbye and disconnection
        async def say_goodbye_and_disconnect():
            print("Agent is saying goodbye")
            await agent.say("Thank you for calling. Goodbye!", allow_interruptions=False)

            # Introduce a delay of 3 seconds
            await asyncio.sleep(3)

            # Disconnect from the room
            await ctx.room.disconnect()
            print("Disconnected from the room.")

            # Shutdown the job
            ctx.shutdown()
            print("Job shutdown completed.")

        # Call the function to say goodbye and disconnect
        await say_goodbye_and_disconnect()

    except Exception as e:
        print(f"Error occurred: {e}")
    finally:
        # Ensure cleanup
        if ctx.room.connection_state != rtc.ConnectionState.CONN_DISCONNECTED:
            await ctx.room.disconnect()
            print("Disconnected from room.")

if __name__ == "__main__":
    cli.run_app(WorkerOptions(
        entrypoint_fnc=entrypoint
    ))
This code introduces a 3-second delay after the agent says "Thank you for calling. Goodbye!" before disconnecting from the room. Let me know if you need further assistance! Sources: - https://livekit-users.slack.com/archives/C07FY8WHGPM/p1729822736.610669 - https://livekit-users.slack.com/archives/C07FY8WHGPM/p1732016597.012059 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.
m
@millions-hair-24956 here where particiapant get connected
g
In the context of LiveKit, a participant gets connected to a room when the
wait_for_participant
method is called on the
JobContext
object. This method waits for a participant to join the room and returns the participant object once they are connected. Here's a basic example of how this is typically done:
Copy code
async def entrypoint(ctx: JobContext):
    await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
    participant = await ctx.wait_for_participant()
    print(f"Participant {participant.identity} has joined the room")
In this example, the
wait_for_participant
method is used to pause the execution until a participant joins the room, at which point it returns the participant object. Would you like more details on this process? Sources: - LiveKit Docs - JobContext 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.