Anotações de Reunião LLM API: Transcrição para Resumo em Python
Para obter anotações de reunião LLM API, você envia a transcrição para um endpoint de chat completions com um prompt de sistema curto e lê a resposta. Os elementos que determinam a qualidade são o prompt, um formato de saída fixo e como você lida com gravações longas.
Atualizado

Pontos principais
- Uma única chamada de chat completion transforma uma transcrição em anotações; o modo JSON oferece um formato fixo.
- Uma janela de 100.000 tokens comporta a maioria das transcrições de reuniões sem fragmentação.
- Peça ao modelo para escrever null para proprietários e datas ausentes, para que ele não os invente.
- Uma chave completa permite 8 requisições simultâneas, suficientes para processar um dia de reuniões em paralelo.
O pipeline em quatro etapas
- Grave e transcreva. Use qualquer ferramenta de transcrição de voz. Esta API é apenas de texto e não aceita áudio.
- Prepare o texto. Adicione um cabeçalho com o título da reunião, data e nomes dos participantes. Rótulos de falante, se você os tiver, ajudam muito.
- Chame o modelo. Envie a transcrição com um prompt de sistema que defina as seções desejadas.
- Armazene e compartilhe o resultado. Salve o JSON, renderize como Markdown ou HTML, publique onde a equipe lê.
O endpoint é POST /v1/chat/completions em https://api.whisperapis.com/v1, o ID do modelo é uncensored e qualquer SDK OpenAI funciona após alterar a URL base e a chave. Se precisar configurar a transcrição de voz primeiro, a documentação de início rápido cobre a parte de texto e qualquer servidor compatível com Whisper pode fornecer a transcrição.
Obtenha anotações estruturadas com modo JSON
Resumos livres são bons para leitura, mas um pipeline precisa de campos que possa armazenar e filtrar. O modo JSON, habilitado com response_format definido como {"type": "json_object"}, faz o modelo retornar um único objeto JSON. Descreva as chaves no prompt de sistema e use a palavra JSON lá, pois o prompt é o que define o formato.
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"])Duas linhas nesse prompt fazem a maior parte do trabalho. "Use apenas o que a transcrição diz" impede que o modelo adicione detalhes plausíveis. "Se um proprietário ou uma data não forem informados, escreva null" dá a ele uma forma válida de dizer que não sabe, o que é melhor do que um nome inventado. Uma temperatura baixa, como 0,2, reduz a variação entre execuções, o que você deseja quando a mesma transcrição pode ser processada duas vezes.
Analise sempre de forma defensiva. Envolva json.loads em um bloco try e, em caso de falha, tente novamente uma vez. Requisições falhas não são cobradas e uma única tentativa corrige a maioria dos erros de formatação pontuais.
Transmita o resultado para quem está esperando
Se alguém clicar em um botão e esperar pelas anotações, mostre o texto conforme ele chega. Defina stream como true e a API envia eventos enviados pelo servidor; o uso é incluído no final do stream.
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)O streaming tem um detalhe operacional: uma solicitação em streaming mantém seu slot de concorrência até o fim do streaming. Uma chave completa permite 8 ao mesmo tempo, uma chave de teste 2. Se uma aba do navegador for fechada e seu servidor continuar lendo, esse slot fica ocupado, então cancele a solicitação upstream quando o cliente se desconectar.
Para trabalhos em lote que ninguém observa, pule o streaming. Uma requisição simples é mais fácil e você obtém toda a resposta em um único objeto.
Reuniões longas e a janela de 100k
A janela de contexto é de 100.000 tokens, contando o prompt e a resposta juntos. Uma reunião de uma hora tem cerca de 9.000 palavras, ou aproximadamente 12.000 tokens, então até um workshop de dia inteiro cabe em uma solicitação. Isso elimina o projeto usual de map-and-reduce onde você divide uma transcrição, resume cada parte e depois resume os resumos. Cada passagem desse projeto perde detalhes, e uma decisão tomada no minuto 5 e revisada no minuto 50 é fácil de relatar incorretamente.
Ainda verifique o tamanho antes de enviar. Uma verificação grosseira é caracteres divididos por quatro para texto em inglês. Se você estiver perto do limite, há duas opções limpas:
- Divida em quebras naturais como itens da pauta, resuma cada uma e passe as anotações parciais para uma chamada final que as mescla.
- Remova conteúdo que não importa, como longos trechos de conversa fiada antes do início da reunião.
O corpo máximo da requisição é 8 MB, o que não é um limite prático para texto. Os prompts não são usados para treinamento, o que importa se as gravações incluírem planos internos ou nomes de clientes.
Detalhes do prompt que alteram a saída
Diga para quem são as anotações
"Notas para um engenheiro que perdeu a reunião" obtém detalhes diferentes de "uma atualização de um parágrafo para a equipe executiva". Escreva o leitor no prompt do sistema.
Forneça ao modelo a lista de participantes
A transcrição de fala para texto frequentemente embaralha nomes. Uma linha como "Participantes: Priya Nair (PM), Tom Ortiz (backend), Lena Fischer (design)" permite que o modelo repare uma transcrição que diz "Tom Ortis" e anexe tarefas à pessoa correta.
Peça decisões e ações separadamente
Uma decisão é algo em que o grupo concordou. Uma ação é algo que uma pessoa fará. Quando ambos existem em uma lista, os leitores a ignoram. Chaves separadas tornam a distinção explícita, e o modelo a segue consistentemente.
Mantenha o conteúdo sensível
Reuniões reais contêm linguagem direta, reclamações sobre pessoas nomeadas, preocupações legais e disputas acaloradas. O modelo aqui é ajustado para responder sem recusas de conteúdo para uso lícito de adultos, então ele resume o que foi dito em vez de recusar. Você ainda é dono da saída, então revise as anotações antes de enviá-las para pessoas que não estavam na sala.
Executando um dia inteiro de reuniões
Uma equipe que grava seis reuniões por dia pode processá-las em paralelo. Com 8 requisições simultâneas, envie até oito de cada vez; um pequeno conjunto de processos com um semáforo faz o trabalho. O limite por minuto para uma chave completa é de 300 requisições, o que um pipeline de reunião não atingirá.
Node funciona da mesma forma que Python. Aqui está a versão sem streaming:
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);Se você receber HTTP 429, leia o código de erro. concurrency significa muitas requisições de uma vez, então reduza o tamanho do conjunto. rate_limited significa muitas por minuto. Um 429 com um cabeçalho Retry-After: 5 sinaliza sobrecarga temporária; aguarde cinco segundos e tente novamente.
Verificando as anotações antes de confiar nelas
Anotações geradas parecem confiantes mesmo quando estão erradas, então inclua algumas verificações baratas no pipeline em vez de depender de um humano para notar.
- Verificação de citação. Peça uma citação curta de apoio com cada item de ação, depois pesquise a transcrição por ela. Uma citação que não aparece é um sinal de que o item foi inventado.
- Verificação de responsável. Compare cada responsável com sua lista de participantes e sinalize nomes que não estão nela.
- Verificação de vazio. Uma reunião sem decisões é possível, mas um resultado com todos os arrays vazos em uma transcrição de 40 minutos geralmente significa que a entrada foi truncada ou o arquivo estava errado.
- Verificação de comprimento. Anotações mais longas que cerca de um quinto da transcrição não são anotações; ajuste o prompt ou defina
max_tokens.
Registre o cabeçalho de resposta X-Request-Id ao lado de cada resultado salvo. Quando alguém disser que um item de ação está errado, esse identificador permite encontrar a requisição e compará-la com a transcrição. Manter a transcrição original ao lado das anotações é barato e resolve a maioria das disputas rapidamente.
Custo e um primeiro teste
O preço é $0,15 por milhão de tokens de entrada e $0,50 por milhão de tokens de saída. Uma reunião de uma hora com transcrição de 12.000 tokens e conjunto de anotações de 800 tokens custa $0,0018 para entrada e $0,0004 para saída, totalizando $0,0022. A essa taxa, $1 cobre cerca de 454 reuniões. Veja a página de preços para recargas, que começam em $20 e podem ser pagas por cartão ou cripto.
Para experimentar, cadastre-se e abra a página de chave de API. Um crédito de teste de um clique de $0,50 está disponível uma vez por pessoa, válido por 7 dias, sem necessidade de cartão. Execute o script Python acima em uma transcrição real, leia o JSON e ajuste o prompt até que os itens de ação correspondam ao que aconteceu na reunião. Depois, repita para o resto.
Mais guias
Perguntas e respostas
Posso enviar gravações de áudio diretamente?
Não. A API aceita apenas texto. Transcreva a gravação com uma ferramenta de transcrição de voz primeiro e, em seguida, envie a transcrição.
Como manter o formato de saída consistente?
Use o modo JSON com um prompt de sistema que nomeie todas as chaves e defina uma temperatura baixa. Analise o resultado em um bloco try e tente novamente uma vez em caso de falha.
Qual o comprimento máximo de uma transcrição que cabe em uma solicitação?
A janela de contexto é de 100.000 tokens para prompt mais resposta. Isso cobre um workshop de dia inteiro na maioria dos casos.
Minhas transcrições são usadas para treinamento?
Não, os prompts não são usados para treinamento.
Qual o custo por reunião?
Uma reunião de uma hora com uma transcrição de 12.000 tokens e um resumo de 800 tokens custa cerca de $0,0022, considerando as taxas de $0,15 por milhão de tokens de entrada e $0,50 por milhão de tokens de saída.
Sua chave está a um formulário de distância
Crie uma conta, copie a chave e altere a URL base. Essa é toda a configuração.