#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Travel Content Creator API v2 旅游内容创作API - 重构版本,基于独立算法包 """ import os import sys import logging from pathlib import Path from contextlib import asynccontextmanager # 添加算法包到路径 sys.path.insert(0, str(Path(__file__).parent.parent / "travel-algorithms")) from fastapi import FastAPI, HTTPException, Depends from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from travel_algorithms import ( create_default_config, create_content_pipeline, create_poster_pipeline, create_document_pipeline, create_crawling_pipeline, AlgorithmConfig ) # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # 全局配置和管道 config: AlgorithmConfig = None content_pipeline: dict = None poster_pipeline: dict = None document_pipeline: dict = None crawling_pipeline: dict = None @asynccontextmanager async def lifespan(app: FastAPI): """应用生命周期管理""" global config, content_pipeline, poster_pipeline, document_pipeline, crawling_pipeline # 启动时初始化 logger.info("🚀 初始化 Travel Content Creator API v2") try: # 创建配置 resource_dir = Path(__file__).parent.parent / "resource" config = create_default_config( resource_base_directory=str(resource_dir), ai_model=os.getenv("AI_MODEL", "qwen-plus"), output_base_directory=os.getenv("OUTPUT_DIR", "output") ) # 设置AI配置 if os.getenv("AI_BASE_URL"): config.ai_model.base_url = os.getenv("AI_BASE_URL") if os.getenv("AI_API_KEY"): config.ai_model.api_key = os.getenv("AI_API_KEY") # 创建各个流水线 content_pipeline = create_content_pipeline(config) poster_pipeline = create_poster_pipeline(config) document_pipeline = create_document_pipeline(config) crawling_pipeline = create_crawling_pipeline(config) logger.info("✅ 所有流水线初始化完成") yield except Exception as e: logger.error(f"❌ 初始化失败: {e}") raise # 关闭时清理 logger.info("🔄 关闭 Travel Content Creator API v2") # 创建FastAPI应用 app = FastAPI( title="Travel Content Creator API v2", description="旅游内容创作API - 重构版本,基于独立算法包", version="2.0.0", lifespan=lifespan ) # 添加CORS中间件 app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 依赖注入函数 def get_config() -> AlgorithmConfig: """获取配置""" if config is None: raise HTTPException(status_code=503, detail="系统未初始化") return config def get_content_pipeline() -> dict: """获取内容生成流水线""" if content_pipeline is None: raise HTTPException(status_code=503, detail="内容生成流水线未初始化") return content_pipeline def get_poster_pipeline() -> dict: """获取海报生成流水线""" if poster_pipeline is None: raise HTTPException(status_code=503, detail="海报生成流水线未初始化") return poster_pipeline def get_document_pipeline() -> dict: """获取文档处理流水线""" if document_pipeline is None: raise HTTPException(status_code=503, detail="文档处理流水线未初始化") return document_pipeline def get_crawling_pipeline() -> dict: """获取爬虫分析流水线""" if crawling_pipeline is None: raise HTTPException(status_code=503, detail="爬虫分析流水线未初始化") return crawling_pipeline @app.get("/") async def root(): """根路径""" return { "name": "Travel Content Creator API v2", "version": "2.0.0", "description": "旅游内容创作API - 重构版本", "features": [ "内容生成 (主题生成、内容创作、内容评判)", "海报生成 (Vibrant模板、透明底图、Fabric.js输出)", "文档处理 (多格式提取、智能整合、格式转换)", "爬虫分析 (小红书爬取、关键词分析、内容分析)", "数据查询 (景区、产品、风格、受众数据)", "工作流管理 (完整流水线、文件上传、任务管理)" ], "endpoints": { "health": "/health", "content": "/api/v2/content/", "poster": "/api/v2/poster/", "document": "/api/v2/document/", "crawling": "/api/v2/crawling/", "data": "/api/v2/data/", "workflow": "/api/v2/workflow/" } } @app.get("/health") async def health_check( config: AlgorithmConfig = Depends(get_config) ): """健康检查""" try: # 检查各个流水线状态 status = { "status": "healthy", "version": "2.0.0", "components": { "content_pipeline": content_pipeline is not None, "poster_pipeline": poster_pipeline is not None, "document_pipeline": document_pipeline is not None, "crawling_pipeline": crawling_pipeline is not None }, "config": { "ai_model": config.ai_model.model_name, "ai_base_url": config.ai_model.base_url or "未配置", "resource_directory": str(config.resources.base_directory) if config.resources.base_directory else "未配置", "output_directory": str(config.output.base_directory) } } return status except Exception as e: return JSONResponse( status_code=503, content={ "status": "unhealthy", "error": str(e) } ) # 导入路由模块 from .routers import content, poster, document, crawling, data, workflow # 注册路由 app.include_router(content.router, prefix="/api/v2/content", tags=["content"]) app.include_router(poster.router, prefix="/api/v2/poster", tags=["poster"]) app.include_router(document.router, prefix="/api/v2/document", tags=["document"]) app.include_router(crawling.router, prefix="/api/v2/crawling", tags=["crawling"]) app.include_router(data.router, prefix="/api/v2/data", tags=["data"]) app.include_router(workflow.router, prefix="/api/v2/workflow", tags=["workflow"]) if __name__ == "__main__": import uvicorn port = int(os.getenv("PORT", 8000)) logger.info(f"🚀 启动 Travel Content Creator API v2 on port {port}") uvicorn.run( "main:app", host="0.0.0.0", port=port, reload=True, log_level="info" )