229 lines
6.9 KiB
Python
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"
|
|
) |