"""应用入口:四库异步生命周期 + 中间件 + 全局异常 + 路由装配。""" from contextlib import asynccontextmanager import asyncio import uvicorn from fastapi import FastAPI from api.router import api_router from config import database from config.database import redis as redis_db from config.settings import settings from agent.advisor_agent.runtime import build_default_runtime as advisor_build_default_runtime from service.customer_agent.bootstrap import ( build_default_knowledge_upload_service, build_default_runtime as customer_build_default_runtime, ) from service.client_agent.bootstrap import build_default_runtime as build_client_runtime from service.client_agent.idle_archive_worker import IdleArchiveWorker from service.advisor.event_consumer import EventConsumer from service.advisor.scheduler import AdvisorScheduler from service.memory.facade import MemoryService from tool.llm import llm as llm_client from utils.exceptions import register_exception_handlers from utils.logger import setup_logging from utils.request_id import RequestIdMiddleware from utils.performance import PerformanceMiddleware class LazyResource: """Construct an application resource on first use and reuse it thereafter.""" def __init__(self, factory): self._factory = factory self._value = None self._initialized = False @property def initialized(self): return self._initialized def _get(self): if not self._initialized: self._value = self._factory() self._initialized = True return self._value def get(self, key, default=None): return self._get().get(key, default) def __getattr__(self, name): return getattr(self._get(), name) @asynccontextmanager async def lifespan(app: FastAPI): setup_logging() app.state.customer_agent_runtime = LazyResource(customer_build_default_runtime) app.state.client_agent_runtime = LazyResource(build_client_runtime) app.state.advisor_agent_runtime = LazyResource( lambda: advisor_build_default_runtime( llm_client=llm_client, memory_service=MemoryService(), ) ) app.state.client_agent_archive_worker = LazyResource( lambda: IdleArchiveWorker( redis=app.state.client_agent_runtime.redis, memory_service=app.state.client_agent_runtime.memory_service, ) ) app.state.client_agent_archive_task = None app.state.advisor_event_consumer = None if settings.advisor.event_consumer_enabled: app.state.advisor_event_consumer = EventConsumer(redis_db.client()) app.state.advisor_event_consumer.start() app.state.advisor_scheduler = None if settings.advisor.scheduler_enabled: app.state.advisor_scheduler = AdvisorScheduler() app.state.advisor_scheduler.start() app.state.knowledge_upload_service = LazyResource( build_default_knowledge_upload_service ) yield worker = app.state.client_agent_archive_worker if worker.initialized: await worker.stop() if app.state.client_agent_archive_task is not None: await app.state.client_agent_archive_task if app.state.advisor_event_consumer is not None: await app.state.advisor_event_consumer.stop() if app.state.advisor_scheduler is not None: app.state.advisor_scheduler.shutdown() await database.dispose() app = FastAPI(title="智能公募基金系统", version="0.1.0", lifespan=lifespan) app.add_middleware(RequestIdMiddleware) app.add_middleware(PerformanceMiddleware) register_exception_handlers(app) app.include_router(api_router) @app.get("/") async def root(): return {"message": "智能公募基金系统 API", "docs": "/docs"} if __name__ == '__main__': uvicorn.run(app, host="127.0.0.1", port=8000)