如何用 LLM API 批量生成短视频脚本?一套可落地的 AI 生文工作流
我做内容时经常遇到一个很具体的卡点:素材已经有了,选题也记在表格里,但轮到写口播稿,光是把同一件事改成不同平台能用的表达,就要耗掉一整个晚上。更麻烦的是,写到第三条时,语气开始重复,标题像复制出来的,剪辑和发布只能往后挪。
后来我把这件事拆成了一个小型流水线:先把选题整理成结构化输入,再让模型生成多个候选,接着用规则做初筛,人工只处理通过筛选的稿子。这里不讨论"让 AI 替你写作",而是把 LLM API 当成一个可重跑的文本处理节点。输入、提示词、输出和修改记录都能保存,下一轮才有机会变得稳定。
先把"批量"定义清楚
一次请求塞进几十个主题,并不等于批量生产。真正可维护的批量流程,至少要满足三件事:每条选题可以独立失败;输出格式固定,方便程序解析;同一批任务能够记录模型、提示词版本和结果。
我会给每条选题准备这些字段:
| 字段 | 用途 |
|---|---|
| topic | 文章或视频要解决的问题 |
| audience | 面向哪类人 |
| scene | 读者在什么场景遇到它 |
| evidence | 可以引用的事实、数据或代码 |
| tone | 口语、教程、复盘等表达方向 |
| constraints | 字数、禁用词、合规要求 |
其中 evidence 很重要。模型可以帮忙组织语言,但不应该替你补一段并不存在的经历或数据。没有证据的地方,我会明确标记为"待人工核验",不让它混进成稿。
用 JSON 约束输出,而不是直接接一段长文本
如果让模型自由写 Markdown,批量跑几轮后,标题格式、标签数量和正文边界都会变。我的做法是先约定一个小而稳定的 JSON 结构:
json
{
"title": "",
"hook": "",
"body": "",
"faq": [],
"tags": [],
"risk_notes": []
}
提示词中把每个字段写清楚,要求只返回 JSON,不要用代码围栏包裹。body 里可以保留 Markdown,但标题、标签和风险提示由外层程序处理。这样即使某条结果解析失败,也只需要重跑这条,不会污染整批任务。
下面是一段 Python 示例,重点不在某个供应商的 SDK,而在于把请求和解析隔开:
python
import json
import os
import time
import requests
API_URL = os.environ["LLM_API_URL"]
API_KEY = os.environ["LLM_API_KEY"]
MODEL = os.environ.get("LLM_MODEL", "your-model")
SCHEMA = {
"title": "string",
"hook": "string",
"body": "markdown string",
"faq": "array of question and answer objects",
"tags": "array of 3 to 5 strings",
"risk_notes": "array of strings"
}
def generate(item):
prompt = f"""
你是一个技术内容编辑。根据输入生成一条短视频脚本草稿。
只使用 evidence 中的事实,不补造经历、数据和产品能力。
输出必须符合这个 JSON 结构:{json.dumps(SCHEMA, ensure_ascii=False)}
输入:{json.dumps(item, ensure_ascii=False)}
"""
response = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": MODEL,
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.6
},
timeout=60
)
response.raise_for_status()
content = response.json()["choices"][0]["message"]["content"]
return json.loads(content)
密钥只从环境变量读取,不要写进脚本,也不要把完整请求日志提交到代码仓库。生产环境里还要给日志脱敏,尤其是输入内容可能包含未公开的选题和客户信息。
提示词不要追求"万能",要拆成几个阶段
我把生成过程分成四段,每一段只解决一个问题。
开头阶段是信息整理。让模型从原始选题中提取受众、场景、冲突和可验证事实,不要求写正文。这个阶段适合检查输入有没有缺字段。
第二段是结构草稿。根据受众和场景给出开头、转折、例子和行动建议。这里不追求华丽,先让内容顺序合理。
第三段才写成口播稿。要求短句、每段只表达一个意思,并在需要停顿的位置加标记。口播稿和博客文章不是一回事,直接把长文章压缩,通常会留下书面腔。
第四段做编辑审查。检查数字是否来自输入、是否出现无法证实的个人经历、是否有过度承诺、是否出现重复标题。审查结果单独返回,不要让模型悄悄改掉原稿,否则很难知道它改了什么。
这种分段方式的好处是可定位。若问题出在事实,就回到信息整理;若问题出在节奏,就重跑口播阶段,不必把整条链路全部重来。
批量任务要有重试边界
接口调用会遇到超时、限流和返回格式错误。简单的无限重试很危险:一次网络抖动可能变成重复扣费,也可能把一条坏输入重复放大。我的任务记录大致长这样:
python
from dataclasses import dataclass
@dataclass
class Job:
id: str
status: str = "pending"
attempts: int = 0
error: str = ""
def run_job(job, payload, max_attempts=3):
while job.attempts < max_attempts:
job.attempts += 1
try:
result = generate(payload)
job.status = "done"
return result
except (TimeoutError, ValueError) as exc:
job.error = str(exc)
if job.attempts < max_attempts:
time.sleep(2 ** job.attempts)
except Exception as exc:
job.status = "failed"
job.error = str(exc)
break
job.status = "failed"
return None
实际使用时,我还会给每条任务加一个幂等键,例如 日期 + 选题 id + prompt_version。重试时先查本地结果表,已经成功的任务不再重复请求。连续失败的任务进入人工队列,并保留原始错误;不要因为"批量必须完整"就把错误吞掉。
质量筛选可以先用规则做掉一半
模型生成的候选稿不用马上交给人看。先做几个便宜的检查:标题长度是否合适,正文是否为空,标签数量是否在范围内,是否包含待核实标记,是否重复出现同一段开场。再做一次敏感词和广告词扫描。
python
FORBIDDEN = {"夸大", "头部", "孤立", "无条件", "长期"}
def check_draft(draft):
errors = []
if not draft.get("title") or not draft.get("body"):
errors.append("标题或正文为空")
if not 3 <= len(draft.get("tags", [])) <= 5:
errors.append("标签数量不在范围内")
text = json.dumps(draft, ensure_ascii=False)
hits = [word for word in FORBIDDEN if word in text]
if hits:
errors.append(f"命中禁用词: {hits}")
if "待人工核验" in text:
errors.append("存在待核验事实")
return errors
规则筛选不是替代编辑,而是把明显问题提前拦截。通过初筛后,我会重点看开头是否有真实问题、例子能不能帮助理解、结尾有没有把同一结论再说一遍。批量生产的价值不在"无人参与",而在把人的时间留给判断和改写。
记录版本,才知道哪次改动有效
建议保存四类信息:输入快照、提示词版本、模型参数、人工修改稿。提示词不要只在聊天窗口里改,给它一个版本号,例如 script-v3。同一组选题用不同版本跑一批,比较通过率、返工点和最终采用率,再决定是否扩大范围。
我还会记录两个很朴素的指标:一次生成后能直接进入编辑的比例,以及人工修改所花的分钟数。只看生成数量,很容易把低质量的堆积误认为提效。假如生成了 100 条,但每条都要从头改,流水线只是增加了清理工作。
结语:把 AI 放在可控的位置
LLM 适合处理重复的改写、归纳和格式化,不适合替人承担事实责任。把任务拆开,用结构化输入约束范围,用 JSON 接住结果,再配上重试、日志和人工复核,才是一条能长期运行的工作流。
如果你也在搭自己的素材工作流,度娘搜『影栈』能看到我做的桌面素材库,欢迎交流。
本文示例仅用于技术学习,实际接入模型 API 时请遵守服务商条款,并对输入内容、版权和个人信息做好合规处理。