Skip to main content
Una trascrizione non è un verbale. È la riunione di nuovo, solo più lunga da leggere di quanto sia stato starci dentro. Quello che le persone vogliono davvero dopo è breve: cosa abbiamo deciso, chi si è impegnato a fare cosa e cosa è ancora aperto. Questo tutorial costruisce esattamente questo, e collega ogni elemento al secondo esatto in cui è stato detto, così puoi andare ad ascoltare la parte con cui non sei d’accordo:
Lungo il percorso faremo:
  1. Trascrivere una registrazione con /audio/transcriptions
  2. Chiedere i tempi, che non tutti i modelli ti daranno
  3. Estrarre decisioni e azioni da fare rispetto a uno schema
  4. Gestire il fatto che la trascrizione non dice mai chi sta parlando
  5. Suddividere una registrazione lunga senza perdere l’orologio

Configurazione

Ti servono Python 3.9 o successivo, il pacchetto requests e una chiave API Venice. Consulta Generare una chiave API se non ne hai una. Porta una qualsiasi registrazione di una conversazione in wav, mp3, m4a, flac, aac, mp4, ogg o webm.

1. Trascrivi la registrazione

/audio/transcriptions è compatibile con OpenAI e accetta un upload multipart. Il file deve essere una vera parte file, dato che il base64 non è accettato su questo endpoint.
La trascrizione viene fatturata in base alla durata dell’audio, non a quanto è stato detto al suo interno, il che rende il costo di una riunione facile da prevedere prima ancora di eseguirla: Chiama GET /models?type=asr per l’elenco corrente invece di fissare questi valori, perché il catalogo cambia.

2. Chiedi i tempi

I timestamp sono ciò che rende le note verificabili, quindi questa è la scelta che conta di più, e l’impostazione predefinita non te li darà:
nvidia/parakeet-tdt-0.6b-v3 è il modello predefinito, e accetta timestamps=true per poi ignorarlo. Non ci sono errori né avvisi, solo una risposta con nient’altro che text al suo interno. Se ti servono i tempi, chiedi un modello che li restituisca e verifica che la chiave sia presente.
Quando un modello restituisce effettivamente i tempi, timestamps è un oggetto e non una lista, e la chiave al suo interno dipende dal modello. Whisper raggruppa per frase, Scribe per parola:
I segmenti a livello di frase hanno la dimensione giusta per questo lavoro. I tempi a livello di parola sono utili per i sottotitoli e sono troppo fini per appendervi una decisione. Appiattiamo quei segmenti in righe con un tempo davanti a ciascuna, che è tutto ciò che serve al modello per citarle dopo:

3. Estrai le note

Descrivi le note che vuoi come uno schema, così il risultato è un record invece di prosa che devi analizzare:
disable_thinking è lì per lo stesso motivo per cui appartiene a qualsiasi passaggio di estrazione. Lo schema decide già la forma della risposta, quindi pagare un modello di reasoning perché ci rifletta sopra non compra nulla e rende il costo di ogni esecuzione diverso dal precedente. Estrarre dati strutturati dai documenti misura quella differenza. Eseguilo su uno standup da cinquantatré secondi e le note tornano con l’orologio annesso:
Ogni spoken_at è reale. Vai al secondo 19,6 e senti la frase che ha creato quel compito.
Dai al modello righe senza tempi e ogni spoken_at torna come 0. Il campo è richiesto, il modello non ha nulla da metterci, e un campo richiesto è un’istruzione a produrre qualcosa piuttosto che un invito a dire che non lo sa. Vale la pena ricordarlo ogni volta che uno schema sembra funzionare: la forma giusta non è la stessa cosa dei valori giusti.

4. Nessuno è etichettato

Due cose in quell’output sono sbagliate, ed entrambe vengono dallo stesso posto. Il responsabile del rollout è May. Il suo nome è Mei. Il riconoscimento vocale è al suo minimo di affidabilità sui nomi propri, e i nomi sono esattamente ciò che serve all’attribuzione, quindi questo è il fallimento che dovresti aspettarti piuttosto che quello sfortunato. L’ultimo elemento è unassigned, anche se qualcuno l’ha chiaramente preso in carico. La riga era “I’ll ask legal today and report back tomorrow”, e la trascrizione registra le parole senza registrare chi le ha dette. Questo secondo caso non è un bug che puoi correggere. Nessun modello di trascrizione Venice esegue la diarizzazione, quindi non c’è alcun campo speaker da cui attingere in nessuno di essi. La trascrizione è un unico flusso di testo senza voce, e i compiti possono essere attribuiti solo quando un nome viene pronunciato ad alta voce, come in “Tomas, can you put the deprecation notice in the changelog”. Il primo puoi correggerlo, dicendo al modello chi era nella stanza:
May viene risolto in Mei Lin perché il modello ora ha una breve lista con cui fare il match, e i responsabili sono nomi completi che il tuo task tracker può cercare. Il terzo elemento rimane non assegnato, correttamente. Un elenco dei partecipanti corregge un errore di ascolto, e nulla recupera informazioni che la registrazione non ha mai trasportato.
Se ti serve una vera attribuzione degli speaker, catturala a monte piuttosto che dedurla a valle. Gli strumenti di conferenza possono registrare una traccia per partecipante, e trascrivere ciascuna traccia separatamente ti dà gli speaker gratis, al costo di una richiesta a persona.

5. Più lungo di una singola richiesta

Gli upload sono limitati a 25 MB, che arrivano prima di quanto penseresti per l’audio non compresso, e una riunione lunga vale comunque la pena di essere suddivisa così che un singolo fallimento non ti costi l’intera trascrizione. Per i file WAV la libreria standard è sufficiente, non serve ffmpeg:
L’offset è tutto il punto. Ogni chunk viene trascritto come se fosse iniziato a zero, quindi i suoi tempi devono essere spostati indietro nella timeline della registrazione originale prima che il modello li veda. È a questo che serve l’argomento offset di timed_lines:
Suddividi lo stesso standup in pezzi da venti secondi e l’orologio rimane onesto attraverso le giunzioni. Le parole no:
Lì è stata detta una sola frase: “Tomas, can you put the deprecation notice in the changelog by Friday?” Il taglio è caduto nel mezzo di essa, quindi il nome è finito in una richiesta e la domanda è finita in un’altra. Whisper ha sentito il nome orfano come una domanda, ha inventato un awesome. per riempire il vuoto alla fine del chunk, e ha trasformato una riga in tre. I tempi sono ancora corretti, e il passo delle note trova ancora il compito. Ciò che perde è il nome, che è la cosa da cui dipende l’attribuzione.
Suddividere su una durata fissa taglia qualcuno a metà a ogni confine. Venti secondi sono abbastanza brevi da colpire una frase quasi ogni volta; dieci minuti lo rendono raro ma non impossibile, e prima o poi cadrà proprio sulla frase che assegna il lavoro. Suddividere sui silenzi evita il problema in modo pulito e richiede uno strumento in grado di trovare gli intervalli, come ffmpeg o pydub. Suddividi solo quando il file lo richiede davvero.
I formati compressi non possono essere tagliati in questo modo, dato che non puoi tagliare un MP3 su un confine di frame con la libreria standard. Usa ffmpeg per quelli:

Mettere il tutto insieme

Prossimi passi

  • Pubblica le azioni da fare sul tuo tracker, usando i nomi dei responsabili che l’elenco dei partecipanti ha risolto.
  • Leggi il riepilogo ad alta voce con Text to Speech per chi ha perso la chiamata.
  • Effettua ricerche tra riunioni passate memorizzando le trascrizioni con gli Embedding.
  • Lascia che un agente decida quando trascrivere e quando rispondere partendo da note che ha già, con Costruire un agente che usa strumenti con il function calling.

Speech-to-Text

Riferimento per l’endpoint di trascrizione.

Estrarre dati strutturati dai documenti

La stessa estrazione schema-first, applicata ai file.

Risposte strutturate

Come json_schema vincola una completion.

Voice Cloning

Dai al riepilogo una voce tutta sua.