2026-09-08 19:17:35 +08:00
|
|
|
"""应用入口:四库异步生命周期 + 中间件 + 全局异常 + 路由装配。"""
|
|
|
|
|
from contextlib import asynccontextmanager
|
2026-09-12 17:48:17 +08:00
|
|
|
import asyncio
|
2026-09-08 19:17:35 +08:00
|
|
|
|
2026-09-10 23:21:30 +08:00
|
|
|
import uvicorn
|
2026-09-08 19:17:35 +08:00
|
|
|
from fastapi import FastAPI
|
|
|
|
|
|
|
|
|
|
from api.router import api_router
|
|
|
|
|
from config import database
|
2026-09-13 16:19:24 +08:00
|
|
|
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
|
2026-09-11 10:47:01 +08:00
|
|
|
from service.customer_agent.bootstrap import (
|
|
|
|
|
build_default_knowledge_upload_service,
|
2026-09-13 16:19:24 +08:00
|
|
|
build_default_runtime as customer_build_default_runtime,
|
2026-09-11 10:47:01 +08:00
|
|
|
)
|
2026-09-11 22:38:15 +08:00
|
|
|
from service.client_agent.bootstrap import build_default_runtime as build_client_runtime
|
2026-09-12 17:48:17 +08:00
|
|
|
from service.client_agent.idle_archive_worker import IdleArchiveWorker
|
2026-09-13 16:19:24 +08:00
|
|
|
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
|
2026-09-08 19:17:35 +08:00
|
|
|
from utils.exceptions import register_exception_handlers
|
|
|
|
|
from utils.logger import setup_logging
|
|
|
|
|
from utils.request_id import RequestIdMiddleware
|
2026-09-13 16:19:24 +08:00
|
|
|
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)
|
2026-09-08 19:17:35 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@asynccontextmanager
|
|
|
|
|
async def lifespan(app: FastAPI):
|
2026-09-11 17:31:16 +08:00
|
|
|
setup_logging()
|
2026-09-13 16:19:24 +08:00
|
|
|
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(),
|
|
|
|
|
)
|
2026-09-12 17:48:17 +08:00
|
|
|
)
|
2026-09-13 16:19:24 +08:00
|
|
|
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
|
2026-09-12 17:48:17 +08:00
|
|
|
)
|
2026-09-08 19:17:35 +08:00
|
|
|
yield
|
2026-09-13 16:19:24 +08:00
|
|
|
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()
|
2026-09-11 17:31:16 +08:00
|
|
|
await database.dispose()
|
2026-09-08 19:17:35 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
app = FastAPI(title="智能公募基金系统", version="0.1.0", lifespan=lifespan)
|
|
|
|
|
|
|
|
|
|
app.add_middleware(RequestIdMiddleware)
|
2026-09-13 16:19:24 +08:00
|
|
|
app.add_middleware(PerformanceMiddleware)
|
2026-09-08 19:17:35 +08:00
|
|
|
register_exception_handlers(app)
|
|
|
|
|
app.include_router(api_router)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/")
|
|
|
|
|
async def root():
|
2026-09-11 22:38:15 +08:00
|
|
|
return {"message": "智能公募基金系统 API", "docs": "/docs"}
|
2026-09-12 17:48:17 +08:00
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
uvicorn.run(app, host="127.0.0.1", port=8000)
|