繁中 ▾
取得 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」提供了一個合法的方式來表示不知道,這比捏造名字更好。較低的 temperature(如 0.2)可降低執行間的差異,這對於可能重複處理的相同逐字稿非常重要。

務必進行防禦性解析。將 json.loads 包在 try 區塊中,若失敗則重試一次。失敗的請求不會計費,且一次重試即可修正大多數的一次性格式錯誤。

將結果串流輸出給等待的使用者

若有人點擊按鈕並等待筆記,請顯示即時到達的文字。將 stream 設為 true,API 將傳送 server-sent events;用量資訊包含在串流結尾。

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,因此即使是一整天的工作坊也能在一次請求中完成。這消除了通常的 map-and-reduce 設計,即分割逐字稿、分別摘要各部分,然後摘要這些摘要。該設計的每次迭代都會遺失細節,且第 5 分鐘做出的決策在第 50 分鐘修訂時很容易誤報。

傳送前仍請檢查大小。粗略的檢查方式是將英文文字的字符數除以四。若接近限制,有兩種乾淨的選項:

  • 在自然斷點(如議程項目)處分割,分別摘要,並將部分筆記傳遞給最終請求以進行合併。
  • 刪除不重要的內容,例如會議開始前長時間的閒聊。

最大請求主體為 8 MB,這對於文字而言並非實際限制。提示詞不會用於訓練,若錄音包含內部計畫或客戶名稱,這很重要。

改變輸出的提示詞細節

說明筆記是給誰看的

"給錯過會議的工程師的筆記" 與 "給執行團隊的一段話更新" 產生的細節層次不同。將讀者寫入系統提示詞。

提供模型與會者名單

語音轉文字常會弄亂名字。類似 "與會者:Priya Nair (PM)、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 金鑰頁面。每人可享有 1 次一鍵試用,提供 $0.50 額度,有效期 7 天,無需信用卡。請對真實的逐字稿執行上方的 Python 腳本,讀取 JSON,並調整提示詞,直到行動項目與會議實際發生的情況相符。接著對其餘部分進行循環處理。

問答

可以直接傳送音訊錄音嗎?

不行。API 僅接受文字。請先使用語音轉文字工具將錄音轉錄,然後傳送轉錄稿。

如何讓輸出格式保持一致?

使用 JSON 模式,並在系統提示詞中列出所有鍵名,同時設定較低的 temperature。在 try 區塊中解析結果,若失敗則重試一次。

一個請求最多能處理多長的轉錄稿?

上下文視窗為 100,000 個 token,包含提示詞與回覆。這在大多數情況下足以涵蓋一整天的工作坊。

我的轉錄稿會用於訓練嗎?

不會,提示詞不會用於訓練。

每場會議的成本是多少?

一場時長一小時、逐字稿為 12,000 個 token、摘要為 800 個 token 的會議,在輸入與輸出 token 每百萬個分別為 $0.15 和 $0.50 的費率下,費用約為 $0.0022。

只差一張表單,即可取得金鑰

建立帳號、複製金鑰、更改基礎 URL。這就是整個設定過程。

取得 API 金鑰