一、系统概述与架构设计
构成了"爆款结构迁移引擎——AI创作平台"的核心后端服务,基于FastAPI框架构建,旨在实现从爆款视频样本分析到新主题内容智能生成的完整工作流。系统采用模块化设计思想,将视频处理、大语言模型交互、素材缺口分析与补全等核心能力解耦,通过标准化的RESTful API对外提供服务。整体架构遵循"数据驱动—智能分析—生成优化"的逻辑闭环,能够处理视频样本的语义提取、爆款结构建模、目标主题适配、内容缺口识别与补全,最终生成结构化的视频脚本(SVT),并支持多版本衍生与人工微调。
系统的核心价值在于将爆款内容的隐性结构显性化,并通过AI能力实现跨主题的结构迁移,大幅降低优质内容的创作门槛。从技术实现来看,平台整合了多媒体处理技术、大语言模型(LLM)推理技术、结构化数据生成技术以及工作流编排能力,形成了一套完整的内容智能生产Pipeline。
二、核心功能模块详解
2.1 基础服务与配置管理
2.1.1 FastAPI应用初始化
app = FastAPI(title="爆款结构迁移引擎 - AI创作平台", version="1.0.0")应用初始化时定义了服务名称和版本号,便于API文档自动生成和服务版本管理。FastAPI基于Starlette和Pydantic构建,提供了异步请求处理、类型校验、自动交互式文档(Swagger UI和ReDoc)等特性,非常适合构建AI驱动的后端服务。
2.1.2 CORS中间件配置
app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )跨域资源共享(CORS)中间件的配置允许前端应用从不同域名访问API服务,开发环境下的宽松配置(allow_origins=["*"])便于前后端分离开发。在生产环境中,应将其限制为具体的前端域名以提升安全性。
2.1.3 核心组件实例化
video_processor = VideoProcessor() llm_client = DoubaoSeed2LiteEngine() gap_engine = GapCompletionEngine()系统在启动时实例化了三个核心组件:
VideoProcessor:负责视频文件的解析与特征提取,是连接原始视频数据与结构化信息的桥梁;
DoubaoSeed2LiteEngine:封装了对豆包Seed2 Lite大模型的API调用,提供文本分析、结构提取、内容生成等NLP能力;
GapCompletionEngine:处理素材缺口的识别与补全逻辑,确保生成内容符合爆款结构的叙事逻辑。
这种依赖注入式的组件管理使得代码结构清晰,便于单元测试和功能扩展。
2.1.4 配置状态检查接口
/api/config-status端点提供了系统配置的健康检查能力,返回火山引擎API密钥、模型端点等关键配置的状态,帮助运维人员快速验证服务就绪情况。这种设计在AI服务中尤为重要,因为大模型API的可用性直接影响核心功能。
2.2 视频样本上传与预处理
2.2.1 上传接口实现
/api/upload-sample端点处理视频文件的上传与初步处理,是整个工作流的入口:
@app.post("/api/upload-sample") async def upload_sample_video(file: UploadFile = File(...)): task_id = str(uuid.uuid4()) save_path = settings.UPLOAD_DIR / f"{task_id}_{file.filename}" with save_path.open("wb") as buffer: shutil.copyfileobj(file.file, buffer) try: sample_data = video_processor.process_sample_video(save_path) return { "task_id": task_id, "filename": file.filename, "sample_data": sample_data, "status": "processed" } except Exception as e: raise HTTPException(status_code=500, detail=f"处理失败: {str(e)}")2.2.2 关键技术细节
任务ID生成:使用
uuid.uuid4()生成全局唯一的任务ID,用于追踪整个处理流程中的相关数据,避免文件命名冲突,同时为分布式部署下的任务调度提供支持。文件存储策略:
利用
settings.UPLOAD_DIR获取配置的上传目录,符合配置集中管理的最佳实践;文件名采用
task_id_original_filename的格式,既保留了原始文件名信息,又确保了唯一性;使用
shutil.copyfileobj高效复制文件流,相比一次性读取文件内容到内存,更适合处理大视频文件。
异常处理机制:通过
try-except块捕获视频处理过程中的异常,并转换为HTTP 500错误返回给客户端,同时保留原始错误信息,便于调试。
2.2.3 VideoProcessor核心功能推测
虽然VideoProcessor的具体实现未给出,但基于其功能定位,可推断其包含以下核心能力:
视频解码:支持常见视频格式(MP4、AVI、MOV等)的解码,提取音频流和视频帧;
音频提取:将视频中的音频轨道分离,为后续ASR(自动语音识别)做准备;
语音转文字:集成ASR引擎(如火山引擎语音识别API),将音频转换为时间戳对齐的文本;
关键帧提取:按固定间隔或场景切换点提取视频帧,用于视觉内容分析;
元数据提取:获取视频时长、分辨率、码率等基础信息。
这些处理步骤将非结构化的视频文件转化为结构化的sample_data,为后续的LLM分析提供标准化输入。
2.3 爆款结构分析引擎
2.3.1 结构分析接口
/api/analyze-structure端点接收视频处理后的样本数据,调用大模型提取爆款视频的结构化模板:
@app.post("/api/analyze-structure") async def analyze_structure(task_id: str = Form(...), sample_data_json: str = Form(...)): try: sample_data = json.loads(sample_data_json) structure_template = await llm_client.analyze_sample_structure(sample_data) print(f"[API-DEBUG] 最终准备返回前端的爆款结构: {json.dumps(structure_template, ensure_ascii=False, indent=2)}") raw_llm = llm_client.last_raw_llm_output print(f"[API-DEBUG] raw_llm_output 有效性: {bool(raw_llm)}, 长度: {len(raw_llm) if raw_llm else 0}") return { "task_id": task_id, "structure_template": structure_template, "raw_llm_output": raw_llm if raw_llm else "", "status": "structure_extracted" } except Exception as e: print(f"[API-ERROR] 结构分析异常: {e}") raise HTTPException(status_code=500, detail=f"结构分析失败: {str(e)}")2.3.2 数据处理流程
JSON反序列化:将前端传入的
sample_data_json字符串解析为Python字典,恢复视频处理得到的结构化数据;LLM结构分析:调用
llm_client.analyze_sample_structure方法,将样本数据发送给豆包Seed2 Lite模型,执行核心的结构分析任务;调试信息输出:通过
print语句输出调试信息,包括结构模板的JSON格式和原始LLM输出,便于开发阶段的问题定位;结果封装返回:将结构模板、原始LLM输出等数据打包返回,其中
raw_llm_output可用于前端展示模型思考过程或进行质量评估。
2.3.3 DoubaoSeed2LiteEngine分析能力
analyze_sample_structure方法是该端点的核心,其实现逻辑可能包含以下关键步骤:
Prompt工程:构建专门的分析提示词,指导模型从样本数据中提取关键结构要素,例如:
视频总时长与时长分布;
叙事段落划分(开场、冲突、高潮、结尾等);
情绪曲线变化;
关键转折点位置;
台词风格与句式特点;
视觉元素与叙事的关联。
API调用封装:封装火山引擎大模型的API调用细节,包括认证(API Key)、模型端点选择、请求参数配置(temperature、max_tokens等)、重试机制等。
响应解析:将LLM返回的自然语言或JSON格式的结果解析为结构化的
structure_template,确保其包含可预测的数据结构,便于后续处理。原始输出缓存:通过
last_raw_llm_output属性保存原始响应,用于调试和分析模型行为。
2.3.4 爆款结构模板数据结构
基于业务逻辑推测,structure_template可能包含以下核心字段:
这种结构化表示使得抽象的"爆款结构"可被机器理解和复用,是实现结构迁移的基础。
2.4 素材缺口识别系统
2.4.1 缺口识别接口
/api/identify-gaps端点负责对比爆款结构模板与目标主题的现有素材,识别需要补充的内容缺口:
@app.post("/api/identify-gaps") async def identify_gaps( task_id: str = Form(...), target_topic: str = Form(...), new_materials_text: str = Form(""), structure_template_json: str = Form(...) ): try: structure_template = json.loads(structure_template_json) gap_analysis = await llm_client.generate_material_gap_analysis(target_topic, new_materials_text, structure_template) print(f"[API-DEBUG] 素材缺口识别结果: {json.dumps(gap_analysis, ensure_ascii=False, indent=2)}") raw_gap = llm_client.last_raw_llm_output print(f"[API-DEBUG] raw_gap_output 有效性: {bool(raw_gap)}, 长度: {len(raw_gap) if raw_gap else 0}") return { "task_id": task_id, "gap_analysis": gap_analysis, "raw_gap_output": raw_gap if raw_gap else "", "status": "gaps_identified" } except Exception as e: print(f"[API-ERROR] 缺口识别失败: {e}") raise HTTPException(status_code=500, detail=f"缺口识别失败: {str(e)}")2.4.2 核心参数解析
target_topic:目标创作主题,如"新手咖啡制作教程",是内容生成的核心指引;
new_materials_text:用户提供的现有素材文本,可能包含产品信息、关键卖点、已有文案等;
structure_template_json:之前步骤生成的爆款结构模板,作为内容框架的基准。
2.4.3 缺口分析逻辑
generate_material_gap_analysis方法的实现逻辑可能包含以下步骤:
素材结构化解析:将
new_materials_text解析为结构化信息,提取关键实体、事实数据、观点主张等;结构需求映射:遍历
structure_template中的每个段落,明确其对内容的需求(如钩子需要痛点问题,解决方案需要具体步骤等);匹配度评估:对比现有素材与结构需求的匹配程度,识别缺失的信息类型;
缺口分类标记:将识别出的缺口进行分类,如:
信息缺口:缺少关键事实、数据或背景信息;
情感缺口:缺乏符合段落情绪要求的情感表达;
逻辑缺口:叙事链条不完整,缺少过渡或因果关联;
风格缺口:素材语言风格与结构要求的风格不符;
视觉缺口:缺少对应段落的视觉呈现建议。
2.4.4 缺口分析结果数据结构
推测gap_analysis的典型结构如下:
这种精细化的缺口分析为后续的内容补全提供了明确的指引,确保生成的内容能够严格遵循爆款结构的框架要求。
2.5 缺口智能补全引擎
2.5.1 补全接口实现
/api/complete-gaps端点调用GapCompletionEngine对识别出的缺口进行智能补全:
@app.post("/api/complete-gaps") async def complete_gaps_endpoint( task_id: str = Form(...), gap_analysis_json: str = Form(...), target_topic: str = Form(...) ): try: gap_analysis = json.loads(gap_analysis_json) completion_result = await gap_engine.complete_gaps(gap_analysis, target_topic) return { "task_id": task_id, "completion_result": completion_result, "status": "gaps_completed" } except Exception as e: print(f"[API-ERROR] 缺口补全失败: {e}") raise HTTPException(status_code=500, detail=f"缺口补全失败: {str(e)}")2.5.2 GapCompletionEngine核心逻辑
GapCompletionEngine是该端点的核心处理器,其内部逻辑可能包含以下模块:
缺口优先级排序:根据缺口类型、所在段落的重要性(如钩子段落的缺口优先级高于结尾段落)对缺口进行排序,确保关键缺口优先得到补全;
补全策略选择:针对不同类型和优先级的缺口采用不同的补全策略:
LLM生成补全:对于创意性内容(如情感化表达、故事化案例),调用大模型生成原创内容;
知识库检索补全:对于事实性信息(如行业数据、产品参数),从内置知识库或外部API(如搜索引擎)检索相关信息;
规则模板补全:对于格式化内容(如步骤说明、清单列表),使用预定义的模板结合变量填充生成;
内容一致性校验:确保补全内容与目标主题、整体风格保持一致,避免逻辑矛盾或风格冲突;
多源融合:将补全内容与用户提供的原始素材进行有机融合,形成连贯的整体。
2.5.3 补全结果数据结构
completion_result可能包含以下关键信息:
补全引擎的输出填补了从缺口分析到内容生成之间的关键环节,使系统具备了端到端的自动化内容生产能力。
2.6 SVT(结构化视频脚本)生成系统
2.6.1 SVT生成接口
/api/generate-svt端点将补全后的素材与爆款结构模板结合,生成最终的结构化视频脚本:
@app.post("/api/generate-svt") async def generate_svt( task_id: str = Form(...), structure_template_json: str = Form(...), gap_analysis_json: str = Form(...), target_topic: str = Form(...), version_type: str = Form("standard") ): try: structure_template = json.loads(structure_template_json) gap_analysis = json.loads(gap_analysis_json) svt_json = await llm_client.generate_svt_json(structure_template, gap_analysis, target_topic, version_type) return { "task_id": task_id, "svt_json": svt_json, "status": "svt_generated" } except Exception as e: print(f"[API-ERROR] SVT生成失败: {e}") raise HTTPException(status_code=500, detail=f"SVT生成失败: {str(e)}")2.6.2 版本类型控制
version_type参数支持生成不同风格的脚本版本,常见的版本类型可能包括:
standard:标准版,平衡信息量与趣味性;
concise:精简版,突出核心信息,适合短视频平台;
detailed:详细版,包含更多背景知识和细节,适合教程类内容;
humorous:幽默版,增加搞笑元素和段子,提升娱乐性;
professional:专业版,使用行业术语,强调权威性和可信度。
2.6.3 SVT数据结构设计
SVT(Structured Video Script)是该系统的核心输出,其数据结构需要同时满足叙事逻辑、拍摄指导和后期制作的多方面需求。一个典型的SVT JSON结构可能如下:
这种高度结构化的脚本格式不仅便于AI生成,也方便导演、摄影师、剪辑师等创作人员理解和执行,实现了从创意到生产的无缝衔接。
2.7 多版本生成与优化
2.7.1 多版本生成接口
/api/generate-multiple-versions端点基于基础SVT生成多个差异化版本,满足不同平台或受众的需求:
@app.post("/api/generate-multiple-versions") async def generate_multiple_versions( task_id: str = Form(...), base_svt_json: str = Form(...), target_topic: str = Form(...) ): try: base_svt = json.loads(base_svt_json) versions = await gap_engine.generate_multiple_versions(base_svt, target_topic) return { "task_id": task_id, "versions": versions, "status": "multiple_versions_generated" } except Exception as e: print(f"[API-ERROR] 多版本生成失败: {e}") raise HTTPException(status_code=500, detail=f"多版本生成失败: {str(e)}")2.7.2 多版本生成策略
GapCompletionEngine.generate_multiple_versions方法可能采用以下策略生成差异化版本:
平台适配:
抖音/快手版:节奏更快,钩子更强烈,加入更多流行梗和网络用语;
B站版:增加深度解析,加入弹幕互动设计,使用更年轻化的语言风格;
小红书版:强调精致感和实用性,增加图文对照元素,突出"种草"属性;
YouTube版:时长更长,结构更完整,加入章节标记和卡片互动。
受众细分:
新手友好版:简化专业术语,增加基础概念解释;
进阶专业版:深入探讨技术细节,使用行业标准术语;
亲子版:调整内容难度,增加家庭场景元素;
职场版:聚焦办公场景应用,强调效率提升。
风格变异:
幽默搞笑版:加入段子、反转和夸张表演;
温情治愈版:使用柔和的音乐、暖色调画面和情感化叙事;
悬疑探秘版:设置悬念和谜题,逐步揭示答案;
干货科普版:强调信息密度,使用图表和数据可视化。
A/B测试优化:针对同一内容点生成不同表达方式,便于后续通过数据反馈优化内容策略。
2.7.3 版本差异化管理
生成的versions数组可能包含版本元数据和差异化内容:
多版本生成能力极大地提升了内容的适配性和传播效率,是工业化内容生产的重要组成部分。
2.8 人工微调接口
2.8.1 手动调整接口
/api/adjust-manually端点允许用户对AI生成的SVT进行精细化调整,平衡AI效率与人类创造力:
2.8.2 调整机制分析
该接口实现了简单的JSON路径覆盖式调整:
调整数据解析:将
adjustments_json解析为键值对,其中键是SVT中的字段路径,值是新的内容;递归更新逻辑:当前实现仅支持顶层键的直接覆盖,更复杂的实现可能需要支持嵌套字段的更新(如使用
a.b.c路径语法);数据一致性维护:调整后可能需要触发验证逻辑,确保修改后的SVT仍然符合结构规范,避免破坏叙事逻辑。
2.8.3 典型调整场景
用户可能进行的调整包括:
修改特定段落的台词文本,使其更符合品牌调性;
调整视觉元素的描述,替换不符合实际场景的画面建议;
更改背景音乐或音效选择;
优化行动号召的文案和呈现方式;
调整段落时长分配,改变整体节奏。
这种人机协作模式充分发挥了AI的高效生成能力和人类的审美判断力,是AI创作平台的理想交互范式。
三、数据结构深度解析
3.1 核心数据流转全景
系统内的数据流转遵循以下路径:
视频文件 → VideoProcessor → sample_data → LLM结构分析 → structure_template → 缺口识别 → gap_analysis → 缺口补全 → completion_result → SVT生成 → svt_json → 多版本生成/人工调整 → 最终脚本每个环节都定义了标准化的数据结构,确保模块间的松耦合和高内聚。
3.2 关键数据结构对比
数据结构名称 | 生成阶段 | 核心作用 | 关键字段示例 |
|---|---|---|---|
| 视频处理 | 存储视频解析结果 |
|
| 结构分析 | 定义爆款内容框架 |
|
| 缺口识别 | 标识内容缺失 |
|
| 缺口补全 | 提供缺失内容 |
|
| SVT生成 | 最终脚本输出 |
|
3.3 数据验证与类型安全
虽然当前代码主要依赖Python的动态类型,但在生产环境中,建议使用Pydantic模型对所有输入输出数据进行严格校验,例如:
from pydantic import BaseModel from typing import List, Optional class Segment(BaseModel): id: str type: str start_time: float end_time: float text: str visuals: Optional[List[dict]] = None class SVT(BaseModel): meta: dict segments: List[Segment] global_settings: dict call_to_action: dict这种强类型定义不仅能提前捕获数据格式错误,还能为API文档提供精确的类型信息,提升开发体验。
四、算法与模型交互逻辑
4.1 大模型交互策略
系统与大模型的交互集中在DoubaoSeed2LiteEngine类中,采用了以下关键策略:
Prompt模板化:为不同任务(结构分析、缺口识别、SVT生成)设计专用Prompt模板,确保模型理解任务目标;
上下文窗口管理:合理控制输入Token数量,对长文本进行分段处理或摘要压缩;
输出格式约束:通过Prompt明确要求模型返回JSON格式,并进行后处理解析;
温度参数调节:根据任务类型调整
temperature参数(如创意生成用较高值,结构化提取用较低值);重试与容错:实现API调用失败重试机制,处理网络波动或服务限流问题。
4.2 爆款结构提取算法
结构提取本质是序列标注与模式识别问题,算法可能包含以下步骤:
文本分段:基于时间戳和语义相似度将转录文本分割为逻辑段落;
特征提取:为每个段落提取文本特征(关键词、情感极性、句式复杂度)和时序特征(位置、时长占比);
模式匹配:将提取的特征与预定义的爆款模式库进行匹配,识别段落类型;
结构建模:基于段落间的时序关系和逻辑关联,构建整体叙事结构模型;
参数优化:通过少量标注数据微调模型,提升结构识别准确率。
4.3 缺口识别算法
缺口识别可建模为多维度匹配问题,算法流程可能包括:
需求向量化:将结构模板中各段落的内容需求转化为多维特征向量;
供给向量化:将现有素材转化为同维度的特征向量;
相似度计算:使用余弦相似度或欧氏距离计算供需匹配度;
阈值判断:低于预设阈值的维度判定为缺口;
优先级排序:基于段落重要性和缺口严重程度计算综合优先级。
4.4 内容生成优化算法
为提升生成内容的质量,系统可能采用以下优化技术:
约束解码:在生成过程中施加约束,确保输出符合SVT的JSON Schema;
多样性采样:在生成多版本时采用Top-p或Top-k采样,增加内容多样性;
奖励模型引导:训练专门的奖励模型评估生成内容的质量,引导生成过程向高分区域探索;
人类反馈强化学习(RLHF):基于人类对生成结果的反馈微调模型,提升内容的人类偏好度。
五、系统优化与扩展方向
5.1 性能优化建议
异步处理优化:对耗时操作(如视频处理、LLM调用)实现真正的异步非阻塞处理,提升并发能力;
缓存机制引入:缓存常用爆款结构模板、LLM响应结果等,减少重复计算和API调用;
流式响应支持:对长文本生成任务实现流式输出,提升用户体验;
批量处理能力:支持批量上传视频和批量生成脚本,满足工业化生产需求。
5.2 功能扩展方向
多模态分析增强:集成图像识别和视频理解模型,直接从视频帧提取视觉特征,丰富样本数据维度;
实时数据接入:接入社交媒体趋势数据,动态调整爆款结构模板,保持内容时效性;
用户反馈闭环:收集用户对生成内容的评价和使用数据,持续优化模型和算法;
协作编辑功能:支持多用户同时编辑SVT,添加评论和批注,提升团队协作效率;
第三方工具集成:对接剪映、Premiere等视频编辑软件,实现从脚本到成片的自动化流程。
5.3 可靠性与安全性提升
输入验证强化:对所有用户输入进行严格的格式和内容验证,防止恶意攻击;
错误处理完善:细化异常类型,提供更友好的错误信息和恢复建议;
日志系统升级:实现结构化日志,支持日志级别控制和集中式日志管理;
权限控制增强:添加用户认证和授权机制,保护知识产权和数据安全;
数据备份恢复:定期备份任务数据和生成的脚本,防止数据丢失。
六、总结
构建的爆款结构迁移引擎AI创作平台,通过整合视频处理、大语言模型和结构化数据生成技术,实现了从爆款视频分析到新主题内容生成的完整自动化流程。系统采用模块化设计,各功能模块职责明确,通过标准化的API进行通信,具备良好的可扩展性和可维护性。
核心价值在于将隐性的爆款内容规律显性化为可复用的结构模板,并通过AI能力实现跨主题的结构迁移,大幅降低了优质内容的创作门槛。系统不仅支持全自动化的内容生成,还提供了人工微调接口,实现了人机协作的最优模式。
未来,通过引入更先进的多模态分析技术、强化学习优化算法和实时数据反馈机制,该系统有望进一步进化,成为更智能、更高效的内容创作助手,为短视频、在线教育、数字营销等领域带来革命性的生产力提升。
源代码
import uuid import json import shutil from fastapi import FastAPI, UploadFile, File, Form, HTTPException from fastapi.middleware.cors import CORSMiddleware from .config import settings from .video_processor import VideoProcessor from .llm_client import DoubaoSeed2LiteEngine from .gap_completion import GapCompletionEngine app = FastAPI(title="爆款结构迁移引擎 - AI创作平台", version="1.0.0") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) video_processor = VideoProcessor() llm_client = DoubaoSeed2LiteEngine() gap_engine = GapCompletionEngine() @app.get("/") async def root(): return {"message": "爆款结构迁移引擎API服务已成功启动", "version": "1.0.0"} @app.post("/api/upload-sample") async def upload_sample_video(file: UploadFile = File(...)): task_id = str(uuid.uuid4()) save_path = settings.UPLOAD_DIR / f"{task_id}_{file.filename}" with save_path.open("wb") as buffer: shutil.copyfileobj(file.file, buffer) try: sample_data = video_processor.process_sample_video(save_path) return { "task_id": task_id, "filename": file.filename, "sample_data": sample_data, "status": "processed" } except Exception as e: raise HTTPException(status_code=500, detail=f"处理失败: {str(e)}") @app.post("/api/analyze-structure") async def analyze_structure(task_id: str = Form(...), sample_data_json: str = Form(...)): try: sample_data = json.loads(sample_data_json) structure_template = await llm_client.analyze_sample_structure(sample_data) print(f"[API-DEBUG] 最终准备返回前端的爆款结构: {json.dumps(structure_template, ensure_ascii=False, indent=2)}") raw_llm = llm_client.last_raw_llm_output print(f"[API-DEBUG] raw_llm_output 有效性: {bool(raw_llm)}, 长度: {len(raw_llm) if raw_llm else 0}") return { "task_id": task_id, "structure_template": structure_template, "raw_llm_output": raw_llm if raw_llm else "", "status": "structure_extracted" } except Exception as e: print(f"[API-ERROR] 结构分析异常: {e}") raise HTTPException(status_code=500, detail=f"结构分析失败: {str(e)}") @app.post("/api/identify-gaps") async def identify_gaps( task_id: str = Form(...), target_topic: str = Form(...), new_materials_text: str = Form(""), structure_template_json: str = Form(...) ): try: structure_template = json.loads(structure_template_json) gap_analysis = await llm_client.generate_material_gap_analysis(target_topic, new_materials_text, structure_template) print(f"[API-DEBUG] 素材缺口识别结果: {json.dumps(gap_analysis, ensure_ascii=False, indent=2)}") raw_gap = llm_client.last_raw_llm_output print(f"[API-DEBUG] raw_gap_output 有效性: {bool(raw_gap)}, 长度: {len(raw_gap) if raw_gap else 0}") return { "task_id": task_id, "gap_analysis": gap_analysis, "raw_gap_output": raw_gap if raw_gap else "", "status": "gaps_identified" } except Exception as e: print(f"[API-ERROR] 缺口识别失败: {e}") raise HTTPException(status_code=500, detail=f"缺口识别失败: {str(e)}") @app.post("/api/complete-gaps") async def complete_gaps_endpoint( task_id: str = Form(...), gap_analysis_json: str = Form(...), target_topic: str = Form(...) ): try: gap_analysis = json.loads(gap_analysis_json) completion_result = await gap_engine.complete_gaps(gap_analysis, target_topic) return { "task_id": task_id, "completion_result": completion_result, "status": "gaps_completed" } except Exception as e: print(f"[API-ERROR] 缺口补全失败: {e}") raise HTTPException(status_code=500, detail=f"缺口补全失败: {str(e)}") @app.post("/api/generate-svt") async def generate_svt( task_id: str = Form(...), structure_template_json: str = Form(...), gap_analysis_json: str = Form(...), target_topic: str = Form(...), version_type: str = Form("standard") ): try: structure_template = json.loads(structure_template_json) gap_analysis = json.loads(gap_analysis_json) svt_json = await llm_client.generate_svt_json(structure_template, gap_analysis, target_topic, version_type) return { "task_id": task_id, "svt_json": svt_json, "status": "svt_generated" } except Exception as e: print(f"[API-ERROR] SVT生成失败: {e}") raise HTTPException(status_code=500, detail=f"SVT生成失败: {str(e)}") @app.post("/api/generate-multiple-versions") async def generate_multiple_versions( task_id: str = Form(...), base_svt_json: str = Form(...), target_topic: str = Form(...) ): try: base_svt = json.loads(base_svt_json) versions = await gap_engine.generate_multiple_versions(base_svt, target_topic) return { "task_id": task_id, "versions": versions, "status": "multiple_versions_generated" } except Exception as e: print(f"[API-ERROR] 多版本生成失败: {e}") raise HTTPException(status_code=500, detail=f"多版本生成失败: {str(e)}") @app.post("/api/adjust-manually") async def adjust_manually( task_id: str = Form(...), svt_json: str = Form(...), adjustments_json: str = Form(...) ): try: svt_data = json.loads(svt_json) adjustments = json.loads(adjustments_json) for key, value in adjustments.items(): if key in svt_data: svt_data[key] = value return { "task_id": task_id, "adjusted_svt": svt_data, "status": "adjusted" } except Exception as e: print(f"[API-ERROR] 手动调整失败: {e}") raise HTTPException(status_code=500, detail=f"手动调整失败: {str(e)}") @app.get("/api/config-status") async def get_config_status(): return { "provider": "", "volcengine_api_key_configured": bool(settings.VOLCENGINE_API_KEY), "doubao_seed_2_lite_model_ep_configured": bool(settings.DOUBAO_SEED_2_LITE_MODEL_EP), "volcengine_base_url": settings.VOLCENGINE_BASE_URL, "ready_to_use": bool(settings.VOLCENGINE_API_KEY and settings.DOUBAO_SEED_2_LITE_MODEL_EP) }