Na Perplexity, damos muita atenção à experiência de quem usa nossos produtos. No caso do Perplexity Comet, nosso navegador com agentes de IA, e do Perplexity Computer, nosso agente digital capaz de executar uma ampla variedade de tarefas, boa parte desse trabalho foi permitir que as pessoas usassem todos os recursos por voz. Há algo especialmente gratificante em poder simplesmente dizer o que você quer, delegar a tarefa e acompanhar a execução. Apostamos na voz como interface porque, quando basta falar para que o produto faça o que você pediu, a interação tem um quê de mágica.
Usamos o Realtime-1.5 em produção para levar essa mágica aos milhões de sessões de voz que a Perplexity gerencia todos os meses. Foi empolgante acompanhar o crescimento do uso da voz na interface do Computer, e aprendemos muito com isso. Compartilhamos aqui algumas descobertas que nos surpreenderam. Experimente o Realtime-1.5 e conte para nós o que você descobriu também.
1. Defina como gerenciar o contexto
Conteúdos longos, especialmente podcasts densos com várias horas de duração, foram um dos testes que melhor mostraram os desafios de gerenciar o contexto. Queríamos que as pessoas pudessem consultar a transcrição de um podcast por voz. A ideia era poder começar a conversa perguntando o que estava acontecendo em um ponto específico, duas horas e meia depois do início do episódio, e receber uma resposta coerente.
A transcrição inteira não cabe na janela de contexto. Na primeira tentativa, enviamos o texto em blocos grandes. Logo descobrimos que, com atualizações grandes, é tudo ou nada. Se você tentar enviar uma atualização de 10.000 tokens para uma janela que só tem espaço para mais 5.000, o modelo perderá todo o histórico anterior. Isso tornava os blocos grandes muito mais arriscados. Bastava uma atualização grande demais para apagar todo um trecho de contexto, em vez de permitir que o sistema descartasse o histórico aos poucos.
Mudamos, então, de abordagem. Passamos a dividir tudo em blocos bem menores, de 2.000 tokens, e a enviá-los aos poucos. Isso exige mais operações, mas o comportamento é muito mais estável. Quando ocorre um truncamento, o modelo perde apenas uma pequena parte do histórico.
Aprendemos também algo menos óbvio. A forma de enviar contexto ao modelo deve variar conforme o conteúdo. Ao usar conversation.item.create para atualizar o contexto, um item com item.type: "message" pode ter um de três papéis: system, user ou assistant. Esses papéis indicam ao modelo que tipo de mensagem ele está recebendo. O papel system serve para dar instruções e orientar o comportamento, user identifica o que o usuário final enviou e assistant identifica a saída gerada pelo modelo.
Quando atribuíamos esses papéis de forma inadequada, a conversa começava a soar estranha. Se enviássemos contexto demais como user, o modelo agia como se a pessoa estivesse lendo em voz alta cada bloco de texto, inclusive trechos de páginas da Web e comentários, quando ela só queria fazer uma pergunta com base naquele material. Se enviássemos contexto demais como system, acontecia o contrário. O modelo deixava de distinguir o que já “sabia”, o que havia recebido como contexto e o que a pessoa estava de fato perguntando naquele momento.
A navegação é um bom exemplo. À medida que a pessoa rola a página, informamos continuamente ao modelo o que aparece na tela. Se apresentarmos tudo isso como entrada do usuário, o modelo começa a agir como se a pessoa tivesse lido cada parágrafo em voz alta. Essa interpretação não corresponde ao que acontece. Queremos que a pessoa sinta que o sistema acompanha a página em segundo plano e responde com naturalidade quando ela faz uma pergunta. Para chegar a esse resultado, o volume de contexto importou menos do que deixar claro o papel de cada mensagem na conversa.
2. Padronize o áudio nas diferentes interfaces do produto
A Perplexity oferece várias interfaces, como Ask, Comet e Computer. Cada uma usa um conjunto diferente de tecnologias no cliente. Swift, TypeScript, Rust e C++ podem gerar buffers de áudio nativos diferentes. Quando deixávamos cada cliente enviar à Realtime API o áudio bruto ou em seu próprio formato nativo, o desempenho variava de um cliente para outro.
Acabamos criando um SDK em Rust para abstrair as diferenças entre plataformas e garantir que todos os clientes seguissem o mesmo contrato ao enviar áudio à API. Na prática, processávamos a forma de onda antes mesmo de ela chegar ao servidor. Primeiro, reamostrávamos o áudio para 48 kHz em mono. Essa é a taxa de amostragem preferencial do codec Opus e a que o WebRTC usa internamente. Em seguida, usávamos o módulo APM do WebRTC para cancelar o eco, controlar o ganho automaticamente, reduzir o ruído e aplicar um filtro passa-altas. Só então codificávamos o áudio para transmissão. Com o SDK, pudemos padronizar as constantes de áudio, fazer a reamostragem e configurar todas as etapas de processamento em um só lugar, sem repetir o trabalho em cada cliente.
3. Faça os ajustes em condições reais de uso
É importante ajustar a detecção de atividade de voz (VAD) nos ambientes em que as pessoas realmente usam o produto. Isso significa calibrá-la com microfones reais, levando em conta o volume dos alto-falantes e o ruído de fundo. Um dos nossos cenários de teste internos era um bar barulhento de São Francisco, porque conseguíamos imaginar alguém usando o produto ali. Uma pessoa pergunta a um amigo: “Você já testou o novo aplicativo da Perplexity?” O amigo pega o celular e, se a interação por voz falhar, acabamos de perder dois usuários. Quando funciona, a reação é mais para “p**ra!”. Esse cenário nos obrigou a acertar os ajustes. O que funciona em condições ideais muitas vezes falha no mundo real. É melhor começar pelos ambientes mais difíceis.
Um dos maiores desafios da experiência por voz foi lidar bem com as pausas. É natural parar para pensar, abrir algo na tela ou se preparar para ler um trecho em voz alta. O modelo pode facilmente interpretar essa pausa como o fim da fala e responder cedo demais. Vimos isso, por exemplo, quando alguém pedia ajuda com uma dedução matemática. A pessoa parava para procurar a fórmula, e o modelo já começava a responder antes que ela terminasse a pergunta. Foi assim que chegamos ao recurso que permite manter a vez de falar. Na abordagem tradicional de pressionar para falar, a voz fica desativada por padrão e a pessoa precisa apertar um botão para falar. Invertemos essa lógica. Por padrão, a interação por voz fica disponível sem precisar apertar nada. Quando a pessoa quer continuar com a palavra por mais um tempo, pode acionar o recurso e decidir quando passar a vez. Vemos nessa ideia algo que vai além de um recurso isolado. À medida que as interfaces de voz passam a fazer parte de fluxos de trabalho mais complexos, acreditamos que alguma versão desse padrão de interação se tornará padrão.
4. Use apenas as ferramentas essenciais e mantenha seus formatos próximos aos usados no treinamento
Limite o conjunto às ferramentas mais importantes. No nosso caso, foram menos de dez. Escolhemos um pequeno conjunto de ferramentas que cobria as ações de maior valor para os usuários. Essa escolha fez sentido e provavelmente trará resultados ainda melhores à medida que surgirem versões mais capazes do modelo.
Incluímos no prompt do sistema instruções explícitas sobre quando e como chamar cada ferramenta. Tomamos o cuidado de manter tanto os schemas das ferramentas quanto suas saídas próximos dos formatos que o modelo viu no treinamento. Na prática, formatávamos as saídas como dados estruturados típicos de ferramentas, sem tentar reproduzir uma fala do assistente. Retornávamos um JSON estruturado com campos bem separados, como response_text para o texto a ser dito ao usuário e sinalizadores como require_repeat_verbatim para orientar o comportamento. Assim, o conteúdo a ser falado ficava separado das instruções. Isso tornou o uso das ferramentas mais estável e manteve o padrão de interação mais próximo do que o modelo provavelmente havia visto durante o treinamento.
// Good:
{
"response_text": "I kicked-off the task to create a market research dashboard",
"require_repeat_verbatim": true
}
// Avoid:
I kicked-off the task to create a market research dashboard
# Response Instructions
Read the above instructions EXACTLY as they are
O Realtime está pronto
O Realtime-1.5 marca uma virada para o setor. Ainda há o que melhorar, especialmente ao lidar com contextos longos, usar um número maior de ferramentas e executar tarefas que exigem mais raciocínio. Esperamos que os modelos continuem melhorando. Na Perplexity, esse futuro já orienta o que construímos hoje. Queremos que as pessoas possam usar bem os sistemas atuais enquanto nos preparamos para a próxima geração de modelos Realtime e para as novas experiências por voz que eles tornarão possíveis.