Заметки по встрече LLM API: от стенограммы к кратким итогам на Python
Чтобы получить заметки по совещанию через LLM API, отправьте стенограмму в эндпоинт чат-завершений с коротким системным промптом и прочитайте ответ. Качество определяется промптом, фиксированной структурой вывода и обработкой длинных записей.
Обновлено

Ключевые моменты
- Один вызов chat completion превращает стенограмму в заметки; JSON-режим дает вам фиксированную структуру.
- Окно на 100 000 токенов вмещает большинство стенограмм совещаний без разбиения на части.
- Укажите модели писать null для отсутствующих ответственных и дат, чтобы она не выдумывала их.
- Полный ключ позволяет выполнять 8 одновременных запросов, чего достаточно для обработки дневного объема совещаний параллельно.
Конвейер в четыре шага
- Запишите и расшифруйте. Используйте любой инструмент распознавания речи. Этот API работает только с текстом и не принимает аудио.
- Подготовьте текст. Добавьте заголовок с названием совещания, датой и именами участников. Метки спикеров, если они у вас есть, очень помогают.
- Вызовите модель. Отправьте стенограмму с системным промптом, определяющим нужные разделы.
- Сохраните и поделитесь результатом. Сохраните JSON, отрендерите его в Markdown или HTML, опубликуйте там, где команда читает заметки.
Эндпоинт — POST /v1/chat/completions на https://api.whisperapis.com/v1, идентификатор модели — uncensored, и любой SDK OpenAI работает после изменения базового URL и ключа. Если сначала нужно настроить распознавание речи, документация по быстрому старту охватывает текстовую часть, а любой сервер, совместимый с Whisper, может предоставить стенограмму.
Получите структурированные заметки с JSON-режимом
Свободные резюме хороши для чтения, но конвейеру нужны поля, которые можно хранить и фильтровать. JSON-режим, включаемый установкой response_format в {"type": "json_object"}, заставляет модель возвращать один объект 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 отправит 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 токенов, включая промпт и ответ вместе. Часовое совещание — это примерно 9 000 слов или около 12 000 токенов, поэтому даже однодневный воркшоп помещается в один запрос. Это устраняет обычную map-and-reduce архитектуру, где стенограмма разбивается, каждая часть суммируется, а затем суммируются сами резюме. Каждый такой шаг теряет детали, и решение, принятое на 5-й минуте и измененное на 50-й, легко сообщить неверно.
Всё равно проверяйте размер перед отправкой. Грубая оценка для английского текста — количество символов, деленное на четыре. Если вы близки к лимиту, есть два чистых варианта:
- Разбейте текст по естественным разрывам, например по пунктам повестки дня, суммируйте каждый и передавайте частичные заметки в финальный вызов для их объединения.
- Удалите контент, который не важен, например длинные отрезки светской беседы до начала совещания.
Максимальный размер тела запроса — 8 МБ, что не является практическим ограничением для текста. Промпты не используются для обучения, что важно, если записи содержат внутренние планы или имена клиентов.
Детали промпта, влияющие на вывод
Укажите, для кого предназначены заметки
"Заметки для инженера, пропустившего совещание" получают другой уровень детализации, чем "одноабзацное обновление для руководства". Укажите читателя в системном промпте.
Предоставьте модели список участников
Распознавание речи часто искажает имена. Строка вида «Участники: Прия Найр (PM), Том Ортис (backend), Лена Фишер (design)» позволяет модели исправить стенограмму, где написано «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 означает слишком много запросов в минуту. 429 с заголовком Retry-After: 5 сигнализирует о временной перегрузке; подождите пять секунд и попробуйте снова.
Проверка заметок перед тем, как им доверять
Сгенерированные заметки звучат уверенно, даже если они неверны, поэтому добавьте несколько простых проверок в конвейер, а не полагайтесь на человека, чтобы он заметил ошибки.
- Проверка цитат. Запросите короткую подтверждающую цитату для каждой задачи, затем найдите её в стенограмме. Цитата, которая не появляется в стенограмме, — признак того, что задача была выдумана.
- Проверка ответственных. Сравните каждого ответственного с вашим списком участников и отметьте имена, которых нет в списке.
- Проверка на пустоту. Совещание без решений возможно, но результат, где все массивы пусты для 40-минутной стенограммы, обычно означает, что входные данные были обрезаны или загружен неверный файл.
- Проверка длины. Заметки длиннее примерно одной пятой части стенограммы — это уже не заметки; ужесточите промпт или установите
max_tokens.
Логгируйте заголовок ответа X-Request-Id рядом с каждым сохраненным результатом. Когда кто-то скажет, что пункт действий неверен, этот идентификатор позволит найти запрос и сравнить его со стенограммой. Хранение оригинальной стенограммы рядом с заметками стоит недорого и быстро разрешает большинство споров.
Стоимость и первый тест
Цена составляет $0,15 за миллион входных токенов и $0,50 за миллион выходных токенов. Часовое совещание со стенограммой на 12 000 токенов и набором заметок на 800 токенов стоит $0,0018 за вход и $0,0004 за выход, итого $0,0022. За эту сумму $1 покрывает около 454 таких совещаний. См. страницу цен для пополнения, которое начинается с $20 и может быть оплачено картой или криптовалютой.
Чтобы попробовать, зарегистрируйтесь и откройте страницу API-ключей. Пробный баланс $0,50 доступен один раз на человека, действует 7 дней, карта не нужна. Запустите приведенный выше скрипт Python на одной реальной стенограмме, прочитайте JSON и настройте промпт, пока пункты действий не начнут совпадать с тем, что произошло на совещании. Затем обработайте остальные.
Дополнительные руководства
Вопросы и ответы
Можно ли отправлять аудиозаписи напрямую?
Нет. API принимает только текст. Сначала расшифруйте запись с помощью инструмента распознавания речи, а затем отправьте стенограмму.
Как сделать формат вывода последовательным?
Используйте JSON-режим с системным промптом, в котором указаны все ключи, и установите низкую температуру. Разберите результат в блоке try и повторите попытку один раз при сбое.
Сколько текста расшифровки влезает в один запрос?
Контекстное окно составляет 100 000 токенов для суммы токенов промпта и ответа. Этого обычно хватает на весь однодневный воркшоп.
Используются ли мои расшифровки для обучения?
Нет, промпты не используются для обучения.
Сколько стоит каждое совещание?
Часовое совещание с расшифровкой на 12 000 токенов и саммари на 800 токенов стоит около $0,0022 при цене $0,15 и $0,50 за миллион входных и выходных токенов.
Ваш ключ — всего в одной форме
Создайте аккаунт, скопируйте ключ, измените базовый URL. Вот и вся настройка.