SonicAgent / src /sonicagent_rt /api /app_factory.py
ruslanmv's picture
Deploy from b942b7d49e31a410e1c1ea8c6f3f7d9bca9586a3
38fccac verified
Raw History Blame Contribute Delete
3.07 kB
"""FastAPI application factory."""
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from sonicagent_rt.api.errors import error_response
from sonicagent_rt.api.middleware import install_upload_limit
from sonicagent_rt.api.routes import health, metrics, models, readiness, sessions, voices
from sonicagent_rt.api.routes.audio import InFlightRequests, router as audio_router
from sonicagent_rt.api.routes.speech_stream import router as speech_stream_router
from sonicagent_rt.api.websocket.endpoint import router as websocket_router
from sonicagent_rt.api.websocket.speech_endpoint import router as speech_socket_router
from sonicagent_rt.config import Settings, get_settings
from sonicagent_rt.speech_stream.store import SpeechStreamStore
from sonicagent_rt.lifespan import app_lifespan
from sonicagent_rt.llm.factory import create_llm
from sonicagent_rt.security.rate_limits import SlidingWindowLimiter
from sonicagent_rt.sessions.manager import SessionManager
from sonicagent_rt.stt.errors import SpeechError
from sonicagent_rt.stt.factory import create_stt_engine
from sonicagent_rt.tts.factory import create_tts_engine
from sonicagent_rt.version import __version__
def create_app(settings: Settings | None = None) -> FastAPI:
resolved = settings if settings is not None else get_settings()
app = FastAPI(title="SonicAgent", version=__version__, lifespan=app_lifespan)
app.state.settings = resolved
app.state.stt = create_stt_engine(resolved)
app.state.tts = create_tts_engine(resolved)
app.state.llm = create_llm(resolved)
app.state.sessions = SessionManager(resolved)
app.state.speech_streams = SpeechStreamStore(
ttl_sec=resolved.session_ttl_sec,
max_sessions=resolved.max_concurrent_sessions,
)
app.state.rate_limiter = SlidingWindowLimiter(resolved.stt_rate_limit_per_minute)
app.state.inflight = InFlightRequests()
@app.exception_handler(SpeechError)
async def handle_speech_error(request: Request, exc: SpeechError):
request_id = request.headers.get("x-request-id")
return error_response(exc, request_id if request_id else None)
origins = resolved.parsed_allowed_origins()
if origins:
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=False,
allow_methods=["GET", "POST", "OPTIONS"],
allow_headers=["Authorization", "Content-Type", "X-Request-Id"],
max_age=600,
)
install_upload_limit(app)
app.include_router(health.router)
app.include_router(readiness.router)
app.include_router(sessions.router, prefix="/v1")
app.include_router(voices.router, prefix="/v1")
app.include_router(models.router, prefix="/v1")
app.include_router(audio_router, prefix="/v1")
app.include_router(speech_stream_router, prefix="/v1")
app.include_router(metrics.router)
app.include_router(websocket_router, prefix="/v1")
app.include_router(speech_socket_router, prefix="/v1")
return app