101 lines
3.0 KiB
Python
101 lines
3.0 KiB
Python
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from abc import ABC, abstractmethod
|
|
from logging import Logger, getLogger
|
|
from typing import TYPE_CHECKING, Optional
|
|
|
|
from anyio import Event
|
|
|
|
from ....doc_utils import export_module
|
|
from .clients.realtime_client import RealtimeClientProtocol
|
|
from .realtime_events import RealtimeEvent
|
|
|
|
if TYPE_CHECKING:
|
|
from .realtime_agent import RealtimeAgent
|
|
|
|
__all__ = ["RealtimeObserver"]
|
|
|
|
global_logger = getLogger(__name__)
|
|
|
|
|
|
@export_module("autogen.agentchat.realtime.experimental")
|
|
class RealtimeObserver(ABC):
|
|
"""Observer for the OpenAI Realtime API."""
|
|
|
|
def __init__(self, *, logger: Optional[Logger] = None) -> None:
|
|
"""Observer for the OpenAI Realtime API.
|
|
|
|
Args:
|
|
logger (Logger): The logger for the observer.
|
|
"""
|
|
self._ready_event = Event()
|
|
self._agent: Optional[RealtimeAgent] = None
|
|
self._logger = logger
|
|
|
|
@property
|
|
def logger(self) -> Logger:
|
|
return self._logger or global_logger
|
|
|
|
@property
|
|
def agent(self) -> "RealtimeAgent":
|
|
if self._agent is None:
|
|
raise RuntimeError("Agent has not been set.")
|
|
return self._agent
|
|
|
|
@property
|
|
def realtime_client(self) -> RealtimeClientProtocol:
|
|
if self._agent is None:
|
|
raise RuntimeError("Agent has not been set.")
|
|
if self._agent.realtime_client is None:
|
|
raise RuntimeError("Realtime client has not been set.")
|
|
|
|
return self._agent.realtime_client
|
|
|
|
async def run(self, agent: "RealtimeAgent") -> None:
|
|
"""Run the observer with the agent.
|
|
|
|
When implementing, be sure to call `self._ready_event.set()` when the observer is ready to process events.
|
|
|
|
Args:
|
|
agent (RealtimeAgent): The realtime agent attached to the observer.
|
|
"""
|
|
self._agent = agent
|
|
await self.initialize_session()
|
|
self._ready_event.set()
|
|
|
|
await self.run_loop()
|
|
|
|
@abstractmethod
|
|
async def run_loop(self) -> None:
|
|
"""Run the loop if needed.
|
|
|
|
This method is called after the observer is ready to process events.
|
|
Events will be processed by the on_event method, this is just a hook for additional processing.
|
|
Use initialize_session to set up the session.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def initialize_session(self) -> None:
|
|
"""Initialize the session for the observer."""
|
|
...
|
|
|
|
async def wait_for_ready(self) -> None:
|
|
"""Get the event that is set when the observer is ready."""
|
|
await self._ready_event.wait()
|
|
|
|
@abstractmethod
|
|
async def on_event(self, event: RealtimeEvent) -> None:
|
|
"""Handle an event from the OpenAI Realtime API.
|
|
|
|
Args:
|
|
event (RealtimeServerEvent): The event from the OpenAI Realtime API.
|
|
"""
|
|
...
|
|
|
|
async def on_close(self) -> None:
|
|
"""Handle close of RealtimeClient."""
|
|
...
|