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」提供了一個合法的方式來表示不知道,這比捏造名字更好。較低的 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。這就是整個設定過程。