2025-07-31 15:35:23 +08:00

229 lines
6.9 KiB
Python

#!/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"
)