LLM API 会议纪要:Python 将转录文本转为摘要
要获取 LLM API 会议记录,请将转录文本发送到聊天补全接口,附带简短的系统提示词并读取回复。决定质量的关键因素是提示词、固定的输出格式以及如何处理长录音。
更新于

要点
- 一次聊天补全接口调用可将转录文本转为记录;JSON 模式可确保固定的输出格式。
- 100,000 token 的窗口无需分块即可容纳大多数会议转录文本。
- 指示模型在所有者和日期缺失时写入 null,以免其编造内容。
- 完整密钥允许 8 个并发请求,足以并行处理一天的会议。
四步流水线
- 录音并转录。 使用任意语音转文本工具。该 API 仅支持文本,不接受音频。
- 准备文本。 添加包含会议标题、日期和参会者姓名的标题。如果有说话人标签,会有很大帮助。
- 调用模型。 发送转录文本,并附带定义所需章节的系统提示词。
- 存储并分享结果。 保存 JSON,将其渲染为 Markdown 或 HTML,发布到团队阅读的地方。
端点为 POST /v1/chat/completions,位于 https://api.whisperapis.com/v1,模型 ID 为 uncensored,更改 base URL 和密钥后,任何 OpenAI SDK 均可使用。如需先设置语音转文本,快速入门文档涵盖了文本部分,任何兼容 Whisper 的服务器均可提供转录文本。
使用 JSON 模式获取结构化笔记
自由格式的摘要适合阅读,但流水线需要可存储和过滤的字段。通过设置 response_format 为 {"type": "json_object"} 启用 JSON 模式,使模型返回单个 JSON 对象。在系统提示词中描述键,并提及 JSON 一词,因为提示词定义了输出格式。
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.whisperapis.com/v1", api_key="YOUR_KEY")
SYSTEM = """You write meeting notes from raw transcripts.
Use only what the transcript says. If an owner or a date is not stated, write null.
Reply with a JSON object with the keys: summary (string), decisions (array of strings),
action_items (array of objects with task, owner, due), open_questions (array of strings)."""
transcript = open("standup.txt", encoding="utf-8").read()
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": "Transcript:\n\n" + transcript},
],
response_format={"type": "json_object"},
temperature=0.2,
)
notes = json.loads(resp.choices[0].message.content)
for item in notes["action_items"]:
print(item["owner"], "->", item["task"], item["due"])提示词中的两行起主要作用。“仅使用转录文本中的内容”可防止模型添加看似合理的细节。“如果未提及所有者或日期,请写 null”为其提供了合理的方式表示不知道,这比编造名字更好。较低的温度(如 0.2)可减少运行间的差异,这对于可能两次处理的同一转录文本很有用。
始终进行防御性解析。将 json.loads 包裹在 try 块中,失败时重试一次。失败的请求不收费,单次重试即可修复大多数一次性格式错误。
将结果流式输出给等待的人
如果有人点击按钮并等待笔记,请显示实时到达的文本。将 stream 设置为 true,API 会发送服务端推送事件;用量包含在流末尾。
from openai import OpenAI
client = OpenAI(base_url="https://api.whisperapis.com/v1", api_key="YOUR_KEY")
transcript = open("standup.txt", encoding="utf-8").read()
stream = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "Write concise meeting notes in Markdown with headings: Summary, Decisions, Actions."},
{"role": "user", "content": transcript},
],
stream=True,
temperature=0.3,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)流式输出有一个操作细节:流式请求会占用并发槽位,直到流结束。完整密钥允许同时处理 8 个,试用密钥允许 2 个。如果浏览器标签页关闭而服务器继续读取,该槽位将保持忙碌,因此当客户端断开连接时取消上游请求。
对于无人值守的批处理任务,跳过流式输出。普通请求更简单,你可以一次性获得整个答案对象。
长会议与 100k 窗口
上下文窗口为 100,000 token,包含提示词和回复。一小时会议大约 9,000 个单词,或约 12,000 token,因此即使是一整天的研讨会也能在一次请求中完成。这消除了通常的分治和归并设计,即拆分转录文本、分别总结各部分,然后总结这些摘要。该设计的每次传递都会丢失细节,第 5 分钟做出的决定和第 50 分钟的修订很容易报告错误。
发送前仍请检查大小。粗略检查方法是英文文本字符数除以四。如果接近限制,有两个清晰的选项:
- 在自然断点(如议程项)处拆分,分别总结,然后将部分笔记传递给最终调用以合并它们。
- 删除无关内容,例如会议开始前的长时间闲聊。
最大请求体为 8 MB,这对文本来说不是实际限制。提示词不用于训练,如果录音包含内部计划或客户名称,这一点很重要。
改变输出的提示词细节
说明笔记是给谁的
"给错过会议的工程师的笔记" 与 "给执行团队的一段更新" 获得的细节不同。将读者写入系统提示词。
提供参会者名单
语音转文本经常混淆姓名。例如“参会人员:Priya Nair(产品经理),Tom Ortiz(后端),Lena Fischer(设计)”这样的文本行,可以让模型修复转录文本中“Tom Ortis”的错误,并将任务分配给正确的人。
分别请求决策和行动
决策是群体达成一致的事项。行动是一个人将要做的事情。当两者列在同一列表中时,读者会跳过它。分离键名使区别明确,模型会一致地遵循。
保留敏感内容
真实会议包含直白的语言、对特定人员的抱怨、法律担忧和激烈争论。此模型经过调整,可在合法成人使用中无内容拒绝地回答,因此它会总结所说内容而非拒绝。你仍拥有输出内容,因此在将笔记发送给未在场的人之前请进行审查。
运行一整天的会议
每天录制六场会议的团队可以并行处理它们。使用 8 个并发请求,一次最多发送八个;带有信号量的小型工作池即可完成工作。完整密钥的每分钟限制为 300 个请求,会议流水线不会达到此限制。
Node 的工作方式与 Python 相同。以下是非流式版本:
import OpenAI from "openai";
import { readFileSync } from "node:fs";
const client = new OpenAI({
baseURL: "https://api.whisperapis.com/v1",
apiKey: process.env.API_KEY,
});
const transcript = readFileSync("standup.txt", "utf8");
const resp = await client.chat.completions.create({
model: "uncensored",
messages: [
{ role: "system", content: "Summarize the meeting in five bullets, then list action items with owners." },
{ role: "user", content: transcript },
],
temperature: 0.2,
});
console.log(resp.choices[0].message.content);如果收到 HTTP 429,请读取错误代码。concurrency 表示同时请求过多,请降低池大小。rate_limited 表示每分钟请求过多。带有 Retry-After: 5 标头的 429 表示临时过载;等待五秒后重试。
在信任笔记之前进行检查
生成的笔记即使内容错误也读起来很笃定,因此请在管道中加入几个低成本检查,而不是依赖人工发现错误。
- 引用检查。 为每个行动项请求简短的支持引用,然后在转录文本中搜索它。未出现的引用表明该条目是编造的。
- 负责人检查。 将每个负责人与参会者名单进行比较,并标记不在名单上的名字。
- 空值检查。 没有决策的会议是可能的,但 40 分钟转录文本的结果如果所有数组都为空,通常意味着输入被截断或文件选错。
- 长度检查。 长度超过转录文本约五分之一的笔记不是合格的笔记;收紧提示词或设置
max_tokens。
在每个保存结果旁边记录 X-Request-Id 响应标头。当某人指出行动项错误时,该标识符可让你找到请求并与转录文本进行比较。将原始转录文本保存在笔记旁边成本很低,并能迅速解决大多数争议。
成本和首次测试
价格为每百万输入 token $0.15,每百万输出 token $0.50。一场时长一小时、转录文本为 12,000 token、笔记为 800 token 的会议,输入成本为 $0.0018,输出成本为 $0.0004,总计 $0.0022。按此费率,$1 可覆盖约 454 场此类会议。查看 定价页面 了解充值,最低充值金额为 $20,可通过信用卡或加密货币支付。
要试用,请注册并打开 API 密钥页面。每人可进行一次 $0.50 的一键试用,有效期 7 天,无需信用卡。在真实转录文本上运行上述 Python 脚本,读取 JSON,并调整提示词,直到行动项与会议实际情况相符。然后循环处理其余部分。
更多指南
问答
可以直接发送音频录音吗?
不行。该接口仅支持文本。请先使用语音转文本工具转录录音,然后再发送转录文本。
如何保持输出格式一致?
使用 JSON 模式,并在系统提示词中列出所有键名,同时设置较低的 temperature 值。在 try 代码块中解析结果,若失败则重试一次。
单次请求能容纳多长的转录文本?
上下文窗口支持 100,000 token,包含提示词和回复。在大多数情况下,这足以覆盖一整天的研讨会内容。
我的转录文本会用于训练吗?
不会,提示词不会用于训练。
每次会议的成本是多少?
一场时长一小时、转录文本为 12,000 token、摘要为 800 token 的会议,在输入 token 价格为 $0.15/百万、输出 token 价格为 $0.50/百万时,成本约为 $0.0022。
只差一张表单,即可获得密钥
创建账户,复制密钥,更改基础 URL。这就是全部设置。