Skip to main content
Ferramentas como o NotebookLM mudaram o que as pessoas esperam de uma pilha de material de pesquisa. Você adiciona fontes, faz perguntas e recebe respostas que apontam de volta para o material, e depois gera uma conversa entre dois apresentadores para escutar durante uma caminhada. Este guia constrói isso, em cerca de duzentas linhas de Python, sobre cinco endpoints da Venice. Nada é armazenado fora da sua máquina exceto as próprias requisições, e a Venice não retém nada disso.

Execute este caderno no Google Colab

Cada passo abaixo em um caderno executável, com a visão geral tocando embutida. Nada para instalar.

Como funciona

Cinco endpoints, cada um fazendo uma tarefa: A recuperação aqui é deliberadamente simples: vetores em uma lista Python, similaridade de cosseno em um loop. Essa é a quantidade certa de maquinário para algumas dezenas de fontes e mantém as partes móveis visíveis. Quando você superar isso, Construindo um bot RAG privado cobre o mesmo pipeline com um banco de dados vetorial de verdade e uma etapa de re-ranking.

Configuração

Uma dependência e uma chave da página de configurações da API.
Crie notebook.py e comece com as importações e a configuração. As duas listas ao final são todo o estado do caderno: sources registra o que você adicionou, e chunks guarda os pedaços pesquisáveis.
HOSTS mapeia o nome de um apresentador a uma voz. Ambas as vozes vêm de tts-xai-v1, e isso importa: as vozes pertencem aos modelos, e enviar uma voz de uma família para um modelo de outra é o erro inicial mais comum com o endpoint de fala.

Escolhendo um modelo que não vai envelhecer

Fixar um modelo de chat em código dentro de um projeto garante que o projeto envelheça. A Venice publica qual modelo ocupa cada papel no momento em /models/traits, então você pode pedir o padrão atual em vez de nomear um.
Outros traits estão disponíveis se este caderno não for o formato que você quer. most_intelligent te dá um modelo mais forte para a sumarização pesada em raciocínio, e default_reasoning te dá um que pensa em aberto. Veja Modelos para a lista completa.

Adicionando fontes

Uma fonte é uma URL ou um arquivo em disco, e a Venice tem um endpoint para cada um. Ambos retornam texto simples, e esse é o ponto: o resto do caderno não se importa de onde uma fonte veio.
/augment/scrape retorna Markdown em vez de HTML bruto, então não há boilerplate para limpar. /augment/text-parser aceita PDF, Word, Excel e texto simples de até 25 MB, e reporta uma contagem de tokens junto com o texto. Processamento de documentos cobre todas as opções.

Chunking e embeddings

Fazer o embedding de um documento inteiro produz um vetor que é uma média de tudo o que ele diz, o que é bruto demais para recuperar uma afirmação específica. Dividi-lo produz vetores em que cada um significa algo. Divida nos limites de parágrafo em vez de por uma contagem fixa de caracteres. Um chunk que termina no meio de uma frase é recuperado mal, porque o embedding é de um fragmento.
embed faz batching porque o endpoint aceita uma lista, e uma requisição para sessenta e quatro chunks é muito mais barata em tempo de execução do que sessenta e quatro requisições. text-embedding-bge-m3 retorna 1024 dimensões e lida bem com fontes multilíngues. Adicionar uma fonte agora é ler, dividir, gerar embeddings e registrar. A magnitude de cada vetor é armazenada junto com ele, porque ela nunca muda e recomputá-la dentro do loop de similaridade é trabalho desperdiçado.
O number é o que possibilita a citação depois. Cada chunk lembra de qual fonte veio, para que uma resposta possa apontar de volta para ela.

Recuperando os trechos certos

Similaridade de cosseno entre o vetor da pergunta e cada vetor de chunk, ordenados, top k. Para alguns milhares de chunks isso roda mais rápido do que a chamada de rede que produziu o vetor da pergunta.

Respondendo com citações

A diferença entre uma resposta fundamentada e um palpite confiante está inteiramente no prompt. Duas instruções fazem o trabalho: responda apenas a partir das notas e diga quando as notas não forem suficientes. Sem a segunda, um modelo vai preencher a lacuna silenciosamente com base na memória, que é justamente o modo de falha que você está tentando eliminar por design. Numerar as notas no prompt dá ao modelo um vocabulário de citação. Ele escreve [2], e você pode resolver isso de volta para uma fonte.
Analisar os colchetes de volta vale a pena por uma linha. Isso te diz quais fontes realmente sustentaram a resposta, que é como você percebe que uma fonte que você achava central nunca é citada.

Escrevendo o roteiro da visão geral

Aqui é onde o caderno deixa de ser uma caixa de busca. Um resumo é algo que você lê; uma visão geral é algo que você escuta, e as duas pedem uma prosa diferente. Diálogo funciona melhor em áudio porque o revezamento faz o ritmo por você, e uma pergunta de um apresentador é uma forma natural de introduzir a próxima ideia. Três restrições importam, e todas as três vêm do áudio, não do texto:
  • Sem markdown, sem URLs. Um modelo de fala lê https://docs.venice.ai um caractere de cada vez.
  • Escreva abreviações por extenso. T E E na primeira vez, não tee.
  • Varie o comprimento dos turnos. Turnos de tamanho uniforme soam como duas pessoas lendo uma lista uma para a outra.
Pedir JSON com um schema é o que torna o resultado renderizável. Texto livre precisaria de parsing, e rótulos de falantes são exatamente o tipo de coisa em que um modelo fica criativo. O enum em speaker significa que todo turno mapeia para uma voz que você tem.
A visão geral cobre as fontes amplamente em vez de responder a uma pergunta, então spread amostra chunks por toda a coleção em vez de recuperar por similaridade. Pegar cada enésimo chunk é rudimentar e funciona bem: ele chega ao final de documentos longos, o que pegar os doze primeiros nunca faria. Trate a contagem de turnos como uma dica em vez de uma instrução. Pedir dezesseis já produziu de dezesseis a vinte e oito aqui, dependendo do quanto as fontes têm a dizer. Se você precisa de um teto rígido, trunque turns antes de renderizar em vez de discutir com o prompt.

Renderizando duas vozes em uma única faixa

Cada turno vira uma requisição de fala, com a voz escolhida por quem está falando.
Ler os frames de cada clipe, em vez de salvar vinte arquivos e costurá-los depois, é o que mantém a junção limpa. Concatenar áudio codificado como MP3 não funciona de forma confiável, porque cada arquivo carrega seus próprios headers. Frames decodificados são apenas samples, então juntá-los é anexar bytes. Dois detalhes fazem o resultado soar intencional. O header da saída vem do primeiro clipe em vez de constantes, para que a taxa de amostragem esteja sempre correta para qualquer modelo escolhido. E um quarto de segundo de silêncio entre turnos dá ao ouvido um tempo para registrar que o falante mudou. Sem isso os apresentadores atropelam os finais um do outro.
pool.map preserva a ordem de entrada, então os turnos voltam na ordem em que foram escritos, não importa qual termine primeiro. Quatro workers é um teto deliberado em vez de um máximo: mais concorrência começará a retornar 429s em tiers mais baixos, e o trabalho já é dominado pelo turno individual mais longo.

Executando

Ingerir e responder leva alguns segundos. O áudio é a parte lenta, e varia com a carga: cerca de seis minutos de fala levam de meio minuto a três minutos para renderizar.

Personalizando

As fontes são todo o jogo. Tudo a jusante é limitado pelo que você coloca. Páginas raspadas trazem sua navegação e rodapés junto, o que é inofensivo para responder mas aparece numa visão geral como um apresentador discutindo com seriedade um índice de documentação. Se isso acontecer, descarte chunks abaixo de um limite de comprimento ou filtre elementos óbvios de layout antes de gerar embeddings. Troque as vozes. HOSTS são duas entradas em um dicionário. tts-xai-v1 traz vinte e seis vozes, e outras famílias têm as suas; GET /models?type=tts lista voices por modelo. Duas vozes que contrastam claramente são mais fáceis de acompanhar do que duas que são meramente diferentes. Clone a sua própria. Clonagem de voz transforma uma amostra curta em um handle de voz que você pode encaixar direto em HOSTS. Adicione um terceiro participante. Nada no pipeline pressupõe dois falantes exceto o enum do schema. Adicionar um entrevistador que só faz perguntas muda bastante o clima. Guarde o roteiro. Escrever turns num arquivo JSON ao lado do áudio custa duas linhas e evita uma nova renderização toda vez que você quiser ajustar uma frase.

Próximos passos

Bot RAG privado

O mesmo pipeline de recuperação com um banco vetorial de verdade e re-ranking.

Respostas citadas com busca na web

Encontre as fontes automaticamente em vez de nomeá-las você mesmo.

Texto para fala

Referência para o endpoint de fala, suas vozes e streaming.

Processamento de documentos

Tudo que o parser de texto aceita, e o que ele retorna.