中文 ▾
获取 API 密钥

LLM API 会议纪要:Python 将转录文本转为摘要

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

更新于

等距会议桌,气泡文字汇聚为上方的清单卡片

要点

  • 一次聊天补全接口调用可将转录文本转为记录;JSON 模式可确保固定的输出格式。
  • 100,000 token 的窗口无需分块即可容纳大多数会议转录文本。
  • 指示模型在所有者和日期缺失时写入 null,以免其编造内容。
  • 完整密钥允许 8 个并发请求,足以并行处理一天的会议。

四步流水线

  1. 录音并转录。 使用任意语音转文本工具。该 API 仅支持文本,不接受音频。
  2. 准备文本。 添加包含会议标题、日期和参会者姓名的标题。如果有说话人标签,会有很大帮助。
  3. 调用模型。 发送转录文本,并附带定义所需章节的系统提示词。
  4. 存储并分享结果。 保存 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。这就是全部设置。

获取 API 密钥