ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AI内容生成平台工程实践:从架构设计到代码实现

2026/8/24 5:03:13 拓冰建站 浏览量
AI内容生成平台工程实践:从架构设计到代码实现 在实际 AI 应用开发领域将创意快速转化为可交互、可传播的媒介形式是许多开发者和创作者面临的共同挑战。特别是对于希望利用 AI 生成视频、短剧或互动内容的团队从模型调用、内容编排到最终发布中间涉及的技术栈和工程实践往往复杂且分散。近期一个名为“漫剧工坊”的项目在 B 站 AI 创造公开赛中亮相并开放试用它瞄准的正是这个痛点——提供一个集成的平台降低 AI 内容创作的门槛。对于开发者而言这不仅仅是一个新工具的上线更是一个观察和学习如何将大模型、AI 生成技术与具体应用场景如漫剧、短剧制作进行工程化结合的绝佳案例。本文将从工程实践的角度深入解析类似“漫剧工坊”的 AI 内容生成平台可能涉及的技术架构、核心模块与开发流程。我们将不局限于某个特定项目而是构建一个概念上的“AI 漫剧工坊”最小可行系统涵盖从创意输入、AI 模型调度、剧本与分镜生成、到视频合成与发布的完整链路。通过这个过程你将理解如何设计一个可用的 AI 应用并掌握其中关键的配置、代码实现与排查方法。1. 理解 AI 内容生成平台的核心架构一个典型的 AI 驱动的内容创作平台如漫剧工坊其核心目标是实现“文本或简单指令 - 多媒体内容”的自动化或半自动化生产。这背后是一套复杂的系统工程而非单个模型的简单调用。1.1 核心工作流与模块划分我们可以将整个流程拆解为几个关键阶段每个阶段对应一个或多个技术模块创意输入与解析模块接收用户的自然语言描述如“生成一个关于未来AI小镇的冒险漫剧”并解析出关键元素角色、场景、情节、风格。剧本与分镜生成模块利用大语言模型LLM将解析后的创意扩展成结构化的剧本包含对话、动作描述和分镜脚本描述每个镜头的画面内容。资产生成模块这是最核心的部分根据分镜脚本并行调用多种 AI 模型生成所需素材。角色与场景图像生成调用文生图模型如 Stable Diffusion生成符合描述的静态画面。角色动作与表情可能需要图生图模型或专门的角色动作模型为静态角色添加动态效果。语音合成调用 TTS 模型为剧本中的对话生成角色语音。背景音乐与音效调用 AI 音乐生成模型或从素材库匹配。时序编排与合成模块将生成的图像、音频、字幕等素材按照分镜脚本的时间线进行精确对齐和合成最终输出视频文件。任务调度与状态管理模块管理整个生成流程中的多个异步任务处理失败重试、资源分配和进度反馈。1.2 关键技术栈选型在工程落地时技术选型需要平衡效果、成本、开发效率和部署复杂度。模块可选技术/服务工程考量点大语言模型 (LLM)OpenAI GPT-4/3.5, Claude, 国内大模型通义千问、文心一言、DeepSeek成本、响应速度、上下文长度、API稳定性。对于剧本生成需要模型有较强的逻辑和创造力。通常将提示词工程化固定输出格式如JSON。文生图模型Stable Diffusion (开源), Midjourney (API), DALL-E 3效果质量、生成速度、版权、成本。开源模型可私有化部署控制成本但需自备GPU资源。商业API简单但持续调用费用高。语音合成Azure TTS, Google TTS, 阿里云 TTS, 开源 TTS (如 VITS)音色选择、自然度、情感支持、并发限制。需要支持多角色不同音色。视频合成FFmpeg (开源), MoviePy (Python库), 专业视频编辑SDK精度、性能、特效支持。FFmpeg 是底层核心MoviePy 提供了更友好的 Python 接口。需要处理大量图片序列和音频轨的同步。任务队列Celery Redis/RabbitMQ, Dramatiq, RQ用于处理耗时的AI模型调用任务实现异步化避免HTTP请求超时。需要关注任务状态持久化和重试机制。后端框架FastAPI, Django, Flask快速构建RESTful API处理用户请求、任务提交和状态查询。FastAPI 的异步支持和自动API文档生成是优势。前端Vue.js, React提供用户交互界面上传创意、查看生成队列、预览和下载成品。注意在实际项目中完全依赖外部商业 API 可能导致成本不可控和单点故障。混合方案核心模型自研或开源部署辅助功能用 API是更常见的工程选择。2. 构建最小可行系统环境与项目结构让我们从一个高度简化的“漫剧工坊”原型开始目标是实现“输入一句话故事梗概输出一个包含5个镜头的短视频”。我们将使用 Python 作为主要开发语言。2.1 环境准备与依赖配置首先确保你的开发环境满足以下要求Python: 3.8 或更高版本。CUDA(如果本地运行图像生成): 适用于你的 NVIDIA GPU 的版本例如 11.8。如果仅使用 API则不需要。FFmpeg: 用于视频合成需全局安装。创建项目目录并初始化虚拟环境mkdir ai_drama_workshop cd ai_drama_workshop python -m venv venv # Windows: venv\Scripts\activate # Linux/Mac: source venv/bin/activate创建requirements.txt文件包含核心依赖# Web 框架与异步处理 fastapi0.104.1 uvicorn[standard]0.24.0 celery5.3.4 redis5.0.1 # AI 模型调用 (示例使用 OpenAI 和 Stability AI 的 API实际需替换为你的密钥) openai1.3.0 stability-sdk0.8.0 # 视频处理 moviepy1.0.3 # 工具类 pydantic2.5.0 python-dotenv1.0.0 requests2.31.0安装依赖pip install -r requirements.txt2.2 项目结构设计一个清晰的项目结构有助于维护和扩展。建议如下ai_drama_workshop/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI 应用入口 │ ├── api/ │ │ ├── __init__.py │ │ └── endpoints.py # API 路由定义 │ ├── core/ │ │ ├── __init__.py │ │ ├── config.py # 配置管理从环境变量读取API密钥等 │ │ └── security.py # 认证相关如需 │ ├── models/ │ │ ├── __init__.py │ │ ├── schemas.py # Pydantic 数据模型请求/响应 │ │ └── task.py # 任务状态数据模型 │ ├── services/ │ │ ├── __init__.py │ │ ├── llm_service.py # LLM 调用服务 │ │ ├── image_service.py # 图像生成服务 │ │ ├── audio_service.py # 音频生成服务 │ │ └── video_service.py # 视频合成服务 │ ├── tasks/ │ │ ├── __init__.py │ │ └── generate_drama.py # Celery 任务完整的漫剧生成流程 │ └── utils/ │ ├── __init__.py │ └── file_utils.py # 文件操作工具 ├── celery_worker.py # Celery Worker 启动文件 ├── .env.example # 环境变量示例文件 ├── requirements.txt └── README.md3. 核心服务模块实现我们将聚焦于三个最核心的服务LLM 剧本生成、图像生成和视频合成。音频生成服务逻辑类似暂不展开。3.1 配置管理 (app/core/config.py)使用环境变量管理敏感信息和配置。from pydantic_settings import BaseSettings from typing import Optional class Settings(BaseSettings): # API Keys (从 .env 文件或环境变量读取) openai_api_key: str stability_api_key: str # 其他服务的密钥... # 模型选择与参数 llm_model: str gpt-3.5-turbo image_model: str stable-diffusion-xl-1024-v1-0 # 路径配置 upload_dir: str ./uploads output_dir: str ./outputs # Celery Redis redis_url: str redis://localhost:6379/0 class Config: env_file .env settings Settings()创建.env文件切勿提交至版本库OPENAI_API_KEYyour_openai_key_here STABILITY_API_KEYyour_stability_key_here3.2 LLM 剧本与分镜生成服务 (app/services/llm_service.py)该服务负责将用户输入的故事梗概转化为结构化的 JSON 数据包含分镜信息。import json import openai from app.core.config import settings from typing import List, Dict, Any openai.api_key settings.openai_api_key def generate_script_and_storyboard(prompt: str) - Dict[str, Any]: 根据用户提示生成剧本和分镜。 返回一个包含场景列表的字典。 system_prompt 你是一个专业的漫剧编剧和分镜师。请根据用户提供的故事梗概生成一个包含5个镜头的简短漫剧分镜脚本。 每个镜头需要包含以下字段并以JSON数组格式输出 1. scene_number: 镜头序号 (从1开始)。 2. description: 该镜头的画面描述用于生成图像。 3. dialogue: 该镜头中的角色对话可以为空。 4. voice_emotion: 对话的情感如 happy, sad, excited若无对话则为空。 输出格式必须是纯JSON不要有任何额外的解释或markdown代码块包裹。 示例输出格式 [ { scene_number: 1, description: 一个年轻的冒险者站在未来AI小镇的入口仰望巨大的全息投影招牌。, dialogue: , voice_emotion: }, { scene_number: 2, description: 冒险者与一个友好的机器人向导在充满霓虹灯的街道上交谈。, dialogue: 机器人欢迎来到AI小镇我是你的向导。, voice_emotion: friendly } ] try: response openai.chat.completions.create( modelsettings.llm_model, messages[ {role: system, content: system_prompt}, {role: user, content: f故事梗概{prompt}} ], temperature0.7, ) content response.choices[0].message.content.strip() # 清理可能存在的 markdown 代码块标记 if content.startswith(json): content content[7:] if content.startswith(): content content[3:] if content.endswith(): content content[:-3] storyboard json.loads(content) return {status: success, storyboard: storyboard} except json.JSONDecodeError as e: return {status: error, message: fLLM 返回了非标准JSON: {e}, raw_output: content} except Exception as e: return {status: error, message: f调用LLM API失败: {e}}关键点解释提示词工程system_prompt定义了 LLM 的角色和严格的输出格式。这是确保后续流程能自动化处理的关键。错误处理LLM 的输出可能不稳定必须捕获JSONDecodeError并做好降级处理例如让任务失败或尝试修复。温度参数temperature0.7在创造性和稳定性间取得平衡可根据需要调整。3.3 图像生成服务 (app/services/image_service.py)这里以调用 Stability AI 的 API 为例。如果你部署了开源的 Stable Diffusion WebUI则可以调用其本地 API。import os import requests from app.core.config import settings from typing import Optional def generate_image(prompt: str, save_path: str) - bool: 根据文本提示生成图像并保存到指定路径。 返回成功与否。 # 使用 Stability AI API 示例 api_host https://api.stability.ai engine_id settings.image_model headers { Authorization: fBearer {settings.stability_api_key}, Accept: image/png } data { text_prompts: [{text: prompt, weight: 1.0}], cfg_scale: 7, height: 768, width: 1024, samples: 1, steps: 30, } try: response requests.post( f{api_host}/v1/generation/{engine_id}/text-to-image, headersheaders, jsondata, ) if response.status_code 200: # 确保保存目录存在 os.makedirs(os.path.dirname(save_path), exist_okTrue) with open(save_path, wb) as f: f.write(response.content) return True else: print(f图像生成API错误: {response.status_code} - {response.text}) return False except Exception as e: print(f图像生成请求失败: {e}) return False生产环境考量本地部署对于高频使用将 Stable Diffusion 部署在自有 GPU 服务器上并通过http://localhost:7860/sdapi/v1/txt2img等接口调用可以显著降低成本和控制延迟。提示词优化传递给文生图模型的prompt需要精心设计通常需要在 LLM 生成的description基础上追加风格化关键词如masterpiece, best quality, anime style和负面提示词nsfw, low quality。失败重试与降级网络或模型不稳定时应有重试机制。甚至可以准备一个默认图片作为降级方案。3.4 视频合成服务 (app/services/video_service.py)使用moviepy库将图片序列、音频和字幕合成为视频。from moviepy.editor import ImageSequenceClip, concatenate_videoclips, AudioFileClip, TextClip, CompositeVideoClip from moviepy.video.fx.all import resize import os from typing import List def create_video_from_storyboard(scene_data_list: List[dict], output_path: str) - bool: 根据分镜数据列表合成视频。 scene_data_list 中的每个 dict 应包含 - image_path: 该镜头对应的图片路径 - audio_path: 该镜头对应的音频路径可选 - duration: 该镜头持续时间秒 - subtitle: 字幕文本可选 clips [] for i, scene_data in enumerate(scene_data_list): # 1. 创建图片片段 img_clip ImageSequenceClip([scene_data[image_path]], durations[scene_data[duration]]) # 统一视频尺寸 img_clip resize(img_clip, (1024, 768)) # 2. 如果有音频合并音频 if scene_data.get(audio_path) and os.path.exists(scene_data[audio_path]): audio_clip AudioFileClip(scene_data[audio_path]) # 确保音频长度不超过图片片段长度 if audio_clip.duration scene_data[duration]: audio_clip audio_clip.subclip(0, scene_data[duration]) img_clip img_clip.set_audio(audio_clip) # 3. 如果有字幕添加字幕简单示例 if scene_data.get(subtitle): # 这里简化处理实际字幕位置、样式需要精细调整 txt_clip TextClip(scene_data[subtitle], fontsize24, colorwhite, bg_colorblack, sizeimg_clip.size) txt_clip txt_clip.set_position((center, bottom)).set_duration(scene_data[duration]) img_clip CompositeVideoClip([img_clip, txt_clip]) clips.append(img_clip) if not clips: return False # 4. 拼接所有镜头 final_clip concatenate_videoclips(clips, methodcompose) # 5. 写入文件 try: # 设置较低的码率和帧率以控制文件大小学习环境适用 final_clip.write_videofile(output_path, fps24, codeclibx264, audio_codecaac) return True except Exception as e: print(f视频合成失败: {e}) return False finally: # 清理临时 clip 对象释放内存 for clip in clips: clip.close() final_clip.close()关键参数说明durations: 每个镜头的停留时间需要根据剧本节奏和对话长度合理设定。resize: 确保所有图片尺寸一致否则合成会出错。fps和codec: 输出视频的帧率和编码器。libx264是广泛兼容的编码器。内存管理moviepy在处理大量或高分辨率图片时可能占用大量内存生产环境需要将合成任务放在独立进程或内存充足的机器上运行并在完成后及时调用close()。4. 异步任务编排与 API 集成单个漫剧生成耗时可能很长几十秒到几分钟必须采用异步任务模式通过 Celery 将耗时操作从 Web 请求中剥离。4.1 定义 Celery 任务 (app/tasks/generate_drama.py)import os import time from celery import Celery from app.core.config import settings from app.services.llm_service import generate_script_and_storyboard from app.services.image_service import generate_image from app.services.audio_service import generate_audio # 假设已实现 from app.services.video_service import create_video_from_storyboard # 创建 Celery 实例 celery_app Celery(drama_tasks, brokersettings.redis_url, backendsettings.redis_url) celery_app.task(bindTrue, namegenerate_drama_task) def generate_drama_task(self, user_prompt: str, task_id: str): 核心的漫剧生成异步任务。 self: Celery 任务实例用于更新状态。 user_prompt: 用户输入的故事提示。 task_id: 任务唯一标识用于前端轮询。 task_dir os.path.join(settings.output_dir, task_id) os.makedirs(task_dir, exist_okTrue) # 步骤1: 生成剧本和分镜 self.update_state(statePROCESSING, meta{step: 1, message: 正在生成剧本和分镜...}) llm_result generate_script_and_storyboard(user_prompt) if llm_result[status] ! success: raise Exception(f剧本生成失败: {llm_result.get(message)}) storyboard llm_result[storyboard] # 步骤2: 为每个分镜生成图像 scene_data_for_video [] for i, scene in enumerate(storyboard): self.update_state(statePROCESSING, meta{step: 2, message: f正在生成第 {i1} 个镜头的图像...}) image_filename fscene_{scene[scene_number]:03d}.png image_path os.path.join(task_dir, image_filename) # 优化提示词将描述加上风格化后缀 image_prompt f{scene[description]}, masterpiece, best quality, anime style, vibrant success generate_image(image_prompt, image_path) if not success: # 可以选择跳过失败镜头或使用占位图 print(f镜头 {scene[scene_number]} 图像生成失败使用占位图。) # 复制一个默认占位图到 image_path # copy_default_image(image_path) # 步骤3: 为有对话的镜头生成语音异步 audio_path None if scene.get(dialogue): self.update_state(statePROCESSING, meta{step: 3, message: f正在生成第 {i1} 个镜头的语音...}) audio_filename fscene_{scene[scene_number]:03d}.mp3 audio_path os.path.join(task_dir, audio_filename) # 调用 TTS 服务 # generate_audio(scene[dialogue], scene.get(voice_emotion, neutral), audio_path) # 收集视频合成所需数据 scene_data_for_video.append({ image_path: image_path, audio_path: audio_path, duration: 5, # 简单设定每个镜头5秒实际应根据对话长度计算 subtitle: scene.get(dialogue, ) }) time.sleep(0.5) # 避免 API 速率限制 # 步骤4: 合成视频 self.update_state(statePROCESSING, meta{step: 4, message: 正在合成最终视频...}) final_video_path os.path.join(task_dir, final_output.mp4) video_success create_video_from_storyboard(scene_data_for_video, final_video_path) if video_success: return { status: SUCCESS, task_id: task_id, video_url: f/outputs/{task_id}/final_output.mp4, # 假设有静态文件服务 message: 漫剧生成完成 } else: raise Exception(视频合成失败)4.2 创建 FastAPI 端点 (app/api/endpoints.py)提供提交任务和查询任务状态的接口。from fastapi import APIRouter, BackgroundTasks, HTTPException from pydantic import BaseModel from typing import Optional import uuid from app.tasks.generate_drama import generate_drama_task, celery_app router APIRouter() class DramaRequest(BaseModel): prompt: str class TaskStatusResponse(BaseModel): task_id: str status: str # PENDING, PROCESSING, SUCCESS, FAILURE current_step: Optional[int] None message: Optional[str] None result: Optional[dict] None router.post(/generate, response_modeldict) async def create_drama_generation_task(request: DramaRequest, background_tasks: BackgroundTasks): 提交一个新的漫剧生成任务 task_id str(uuid.uuid4()) # 将任务发送给 Celery 异步执行 task generate_drama_task.apply_async(args[request.prompt, task_id], task_idtask_id) return {task_id: task_id, status_url: f/tasks/{task_id}/status} router.get(/tasks/{task_id}/status, response_modelTaskStatusResponse) async def get_task_status(task_id: str): 查询指定任务的状态 task_result celery_app.AsyncResult(task_id) response TaskStatusResponse( task_idtask_id, statustask_result.state, ) if task_result.state PROCESSING: meta task_result.info # 这里 info 是我们在任务中 update_state 设置的 meta if isinstance(meta, dict): response.current_step meta.get(step) response.message meta.get(message) elif task_result.state SUCCESS: response.result task_result.result response.message 任务完成 elif task_result.state FAILURE: response.message str(task_result.info) # 这里 info 是异常信息 return response4.3 启动应用与 Worker主应用 (app/main.py):from fastapi import FastAPI from app.api import endpoints from app.core.config import settings app FastAPI(titleAI漫剧工坊 API) app.include_router(endpoints.router, prefix/api/v1) app.get(/) async def root(): return {message: AI漫剧工坊后端服务运行中}启动 FastAPI 服务uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Celery Worker (celery_worker.py):import os from app.tasks.generate_drama import celery_app if __name__ __main__: celery_app.worker_main([worker, --loglevelinfo])启动 Celery Worker需要先运行 Rediscelery -A celery_worker.celery_app worker --loglevelinfo5. 运行验证与常见问题排查完成以上步骤后一个最小化的 AI 漫剧生成后端就搭建起来了。你可以使用curl或 Postman 进行测试。5.1 测试流程启动服务确保 Redis、FastAPI 和 Celery Worker 都在运行。提交任务curl -X POST http://localhost:8000/api/v1/generate \ -H Content-Type: application/json \ -d {prompt: 一个少年在未来的AI城市中发现了一个古老的秘密}响应应包含task_id。轮询状态curl http://localhost:8000/api/v1/tasks/{task_id}/status观察状态从PENDING-PROCESSING-SUCCESS的变化。获取结果成功后响应中的result字段会包含视频的访问路径需要配置静态文件服务才能直接下载。5.2 常见问题与排查路径在开发和运行过程中你几乎一定会遇到以下问题问题现象可能原因检查方式与解决方案Celery 任务一直处于 PENDING 状态1. Redis 未启动或连接失败。2. Worker 未启动或未正确注册任务。3. 任务函数导入路径错误。1. 检查 Redis 服务状态 (redis-cli ping)。2. 查看 Worker 启动日志确认generate_drama_task被注册。3. 确保celery_worker.py中导入的celery_app对象与任务定义的是同一个。LLM 返回非 JSON 或格式错误1. 提示词不够严格LLM 输出了额外文本。2. 模型temperature参数过高输出随机性大。1. 在system_prompt中更严格地要求“纯JSON无任何额外文本”。2. 降低temperature(如 0.3)。3. 在代码中添加更健壮的解析逻辑尝试用正则提取 JSON 部分。图像生成 API 调用返回 401 或 4291. API 密钥错误或过期。2. 达到速率限制或配额不足。1. 检查.env文件中的密钥是否正确环境变量是否已加载。2. 查看 API 提供商的控制台确认配额和用量。3. 在代码中添加指数退避重试机制。生成的图片风格不一致或质量差1. 传递给文生图模型的提示词不够具体。2. 模型参数如steps,cfg_scale不理想。1. 在image_service.py中优化image_prompt的构建逻辑加入固定的质量关键词和风格关键词。2. 进行参数调优增加steps(如 50) 并微调cfg_scale(如 7-10)。3. 考虑使用 LoRA 或 ControlNet 等微调技术控制风格。视频合成失败或内存不足1. 图片尺寸过大或数量太多。2.moviepy处理高分辨率图片时内存泄漏。1. 在生成图片时控制分辨率如 1024x768。2. 在合成前使用PIL等库将图片统一缩放至目标尺寸。3. 确保在create_video_from_storyboard函数末尾正确调用clip.close()释放资源。4. 考虑将视频合成也放入独立的、内存更大的 Celery Worker 中执行。最终视频没有声音或音画不同步1. 音频文件路径错误或为空。2. 音频长度与镜头duration不匹配。1. 在合成前打印并检查每个scene_data中的audio_path是否存在。2. 在generate_audio服务中确保生成的音频长度与预期镜头时长接近。可以在视频合成时根据音频实际长度动态调整镜头的duration。6. 生产环境最佳实践与扩展方向上述实现是一个用于学习和验证核心流程的“玩具”系统。要将其转化为一个可用的“漫剧工坊”类产品还需要大量的工程化工作。6.1 生产环境部署考量配置与密钥管理切勿将密钥硬编码在代码中。使用专业的配置管理服务如 AWS Secrets Manager, HashiCorp Vault或至少使用 Kubernetes Secrets / Docker Secrets。可观测性集成日志如structlog、指标如 Prometheus和分布式追踪如 Jaeger。记录每个任务的详细日志包括各阶段耗时、模型调用参数和结果。弹性与容错任务重试为 Celery 任务设置autoretry_for对网络超时、API 限流等临时性错误进行自动重试。降级策略当某个 AI 服务如图像生成不可用时应有备选方案如调用备用 API、使用缓存中的素材、返回任务失败但友好的错误信息。队列隔离将图像生成、语音合成等不同资源消耗类型的任务分配到不同的 Celery 队列和 Worker 上避免相互影响。资源与成本优化缓存对相似的提示词生成的图像、语音进行缓存避免重复计算。模型池对于开源模型可以部署多个实例并通过负载均衡器调用。异步批处理如果用户不要求实时可以将多个任务攒批后一起处理提高 GPU 利用率。安全输入过滤对用户输入的prompt进行敏感词过滤防止生成不当内容。输出审核对生成的图片、视频内容进行二次审核可接入内容安全 API。API 限流防止恶意用户刷接口消耗资源。6.2 功能扩展方向更丰富的编辑能力允许用户在生成后对分镜、台词、背景音乐进行在线编辑和重新生成某个特定镜头。角色一致性引入角色 LoRA 或 IP-Adapter 等技术确保同一角色在不同镜头中形象稳定。镜头运动与转场不仅生成静态图利用 AnimateDiff 等技术生成动态镜头并添加专业的视频转场效果。多模态理解允许用户上传参考图、音频来定制风格而不仅仅是文本描述。工作流模板提供“校园恋爱”、“科幻冒险”、“古风武侠”等不同题材的预设工作流和风格模板降低用户创作难度。构建一个成熟的 AI 内容生成平台技术挑战不仅在于调用模型更在于如何将不稳定的 AI 能力通过工程化的手段变得稳定、可靠、可控且成本合理。“漫剧工坊”这类项目的出现正是这一趋势的体现。从本文构建的最小系统出发深入每一个模块解决遇到的具体问题你就能逐步掌握 AI 应用工程化的核心能力。下一步你可以尝试替换文中的示例 API用本地部署的开源模型如 Llama 3、Qwen 2、Stable Diffusion来重构服务这将是对你工程能力的又一次实质性提升。