Publicado em 23 de junho de 2026
Cada sessão LanguageModel tem uma janela de contexto. À medida que uma conversa cresce, o modelo acumula todo o histórico de mensagens no contexto: cada comando do usuário e cada resposta do assistente. Quando a janela é preenchida, o tratamento automático de estouro do navegador é ativado. Ele remove os pares de mensagens mais antigos, um comando e um par de respostas por vez, para liberar espaço para o novo comando. Se o comando recebido for tão grande que a remoção de todo o histórico de conversas não seja suficiente, a chamada falhará completamente com um QuotaExceededError.
A compactação de sessão é uma alternativa proativa: resuma o histórico de conversas com a API
Summarizer
e reinicie uma nova sessão usando esses resumos como initialPrompts. O navegador nunca remove initialPrompts durante o tratamento de estouro de execução. Portanto, o resumo compactado permanece ancorado permanentemente no contexto do modelo, desde que os resumos se encaixem na janela de contexto quando create() for chamado. A nova sessão carrega a mesma conversa com uma fração do custo original do token.
A compactação de sessão oferece às conversas LanguageModel de longa duração uma maneira de permanecer na janela de contexto sem perder a continuidade. As principais etapas são:
- Monitore
contextUsageem relação acontextWindowe mostre isso ao usuário. - Detecte o evento
contextoverflowcomo um aviso antecipado. - Detecte o idioma de cada mensagem com a API Language Detector e resuma-o com uma instância da API Summarizer com reconhecimento de idioma.
- Destrua a sessão antiga e crie uma nova com
initialPrompts. - Mantenha uma cópia
fullHistorypara recuperação de erros.
Acompanhar o uso do contexto
A API Prompt expõe dois atributos para monitorar o quão cheio está o contexto de uma sessão:
session.contextUsage: o número de tokens consumidos no momento.session.contextWindow: a capacidade total de tokens da sessão.
Reflita isso em um elemento <progress> para que os usuários saibam rapidamente o quão perto a
sessão está do limite. Defina value e max diretamente para as contagens de tokens. O navegador dimensiona a barra automaticamente:
<progress id="token-bar" value="0" max="1"></progress>
<label for="token-bar" id="token-label">Context: — / — tokens</label>
function updateTokenDisplay(session) {
const usage = session.contextUsage;
const total = session.contextWindow;
tokenBar.value = usage;
tokenBar.max = total;
tokenLabel.textContent =
`${Math.round(usage)} / ${Math.round(total)} tokens ` +
`(${Math.round((usage / total) * 100)}%)`;
}
Chame updateTokenDisplay() após cada resposta de comando para que a barra permaneça atual.
Detectar estouro de contexto
Quando um novo comando excede o contexto restante, a recuperação automática do navegador começa: ele remove os comandos e pares de respostas mais antigos um de cada vez até liberar espaço suficiente. O evento contextoverflow é acionado no momento em que essa remoção começa. Registre um handler imediatamente após criar a sessão:
session.addEventListener('contextoverflow', () => {
showWarning('⚠ Context window nearly full. Consider compacting the session.');
});
Há duas propriedades importantes desse comportamento de remoção:
initialPromptsnão são removidos no momento da execução. O navegador não os remove para abrir espaço para um comando recebido. No entanto, se o tamanho combinado de oinitialPromptstransmitido paraLanguageModel.create()for muito grande para caber na janela de contexto,create()será rejeitado com umQuotaExceededError. Portanto, verifique se a compactação é pequena o suficiente para continuar a conversa.- A remoção tem um limite. Se o comando recebido for tão grande que a remoção de toda a conversa anterior ainda não seja suficiente, a chamada
prompt()oupromptStreaming()falhará com umQuotaExceededErrore nada será removido.
Leia mais sobre tratamento de estouro de contexto na documentação da API Prompt .
Use o evento contextoverflow para avisar o usuário, desativar o botão de envio ou acionar a compactação automaticamente antes que o navegador comece a descartar silenciosamente o histórico de conversas.
Compactar a sessão
A compactação tem três etapas:
- Resuma cada mensagem no histórico de conversas com a API Summarizer.
- Destrua a sessão antiga.
- Crie uma nova sessão com os resumos como
initialPrompts.
Resumir o histórico
A API Summarizer é uma opção natural para compactar mensagens de chat individuais. Para cada mensagem, primeiro detecte o idioma dela com a API Language Detector para que o resumo possa ser configurado corretamente:
async function detectLanguage(text, threshold = 0.7) {
const detector = await LanguageDetector.create();
const results = await detector.detect(text);
if (results.length > 0 && results[0].confidence >= threshold) {
return results[0].detectedLanguage;
}
return null; // confidence too low — caller falls back to navigator.language
}
O limite de confiança 0.7 evita agir em detecções incertas. Quando a confiança estiver abaixo do limite, volte para navigator.language.
Em seguida, crie um resumo configurado para o idioma detectado. Prefira
preference: 'speed' para selecionar a variante de modelo menor e de latência mais baixa e
volte para preference: 'auto' se o modelo mais rápido não oferecer suporte ao
idioma detectado:
const summarizers = {}; // cache, keyed by `${format}:${lang}`
async function getSummarizer(format, lang) {
const key = `${format}:${lang}`;
if (summarizers[key]) return summarizers[key];
const baseOptions = {
type: 'tldr',
format, // 'markdown' or 'plain-text'
length: 'short',
expectedInputLanguages: [lang],
expectedContextLanguages: [lang],
outputLanguage: lang,
};
let options = { ...baseOptions, preference: 'speed' };
let avail = await Summarizer.availability(options);
if (avail === 'unavailable') {
options = { ...baseOptions, preference: 'auto' };
avail = await Summarizer.availability(options);
}
if (avail === 'unavailable') {
throw new Error('Summarizer API unavailable on this device.');
}
summarizers[key] = await Summarizer.create(options);
return summarizers[key];
}
O armazenamento em cache de resumos por par format+lang evita chamadas create() redundantes quando mensagens consecutivas compartilham o mesmo idioma.
O argumento format é derivado do próprio conteúdo da mensagem. Especificar
'markdown' para prosa simples pode introduzir formatação indesejada, e especificar
'plain-text' para Markdown remove cercas de código e ênfase. Uma pequena expressão regular distingue os dois:
function looksLikeMarkdown(text) {
return /(?:^#{1,6} |^[-*+] |\d+\. |\*\*|__|\[.+?\]\(|^> |^```)/m.test(text);
}
Com o idioma e o formato resolvidos, resuma cada mensagem e transmita uma string context para que o modelo entenda que está compactando um turno de chat, não um documento independente:
const compacted = [];
for (const msg of history) {
const lang = (await detectLanguage(msg.content)) ?? navigator.language;
const format = looksLikeMarkdown(msg.content) ? 'markdown' : 'plain-text';
const summarizer = await getSummarizer(format, lang);
const summary = await summarizer.summarize(msg.content.trim(), {
context:
`This is a ${msg.role} turn from a chat conversation. ` +
`Preserve its key meaning as concisely as possible.`,
});
// Only use the summary if it's actually shorter.
compacted.push({
role: msg.role,
content:
summary.trim().length < msg.content.length ? summary.trim() : msg.content,
});
}
Destruir a sessão antiga
Libere os recursos da sessão antiga antes de criar a substituição:
session.destroy();
session = null;
Criar uma nova sessão com histórico compactado
Transmita as mensagens compactadas como initialPrompts para criar a nova sessão com o contexto da conversa:
// Collect every language the detector was confident about.
const sessionLangs =
confidentLangs.size > 0 ? [...confidentLangs] : [navigator.language];
session = await LanguageModel.create({
expectedInputs: [{ type: 'text', languages: sessionLangs }],
expectedOutputs: [{ type: 'text', languages: sessionLangs }],
initialPrompts: compacted,
});
// Re-register the overflow handler on the new session.
session.addEventListener('contextoverflow', () => {
/* ... */
});
A nova sessão começa com um contextUsage mais baixo. A conversa continua de onde parou: o modelo tem os resumos como contexto anterior, para que possa responder a perguntas de acompanhamento sobre tópicos anteriores.
Solucionar erros
Se a criação de resumo ou sessão falhar depois que a sessão antiga já tiver sido destruída, o usuário perderá a capacidade de conversar. Mantenha uma matriz fullHistory separada que nunca seja substituída pela compactação e use-a como um fallback de recuperação:
const history = []; // current session's view, replaced on each compaction
const fullHistory = []; // every original message, never overwritten
// In the catch block:
if (!session) {
session = await LanguageModel.create({
initialPrompts: fullHistory.map(({ role, content }) => ({ role, content })),
});
session.addEventListener('contextoverflow', () => {
/* ... */
});
}
A recuperação de fullHistory pode colocar o contexto perto da capacidade novamente, mas o usuário pelo menos volta a um estado de funcionamento e pode tentar outra compactação imediatamente.
Opcionalmente, impeça que alguns conteúdos sejam compactados
Se houver partes críticas de uma mensagem que precisam permanecer sempre no contexto, por exemplo, exemplos de código, processe-as separadamente. O exemplo a seguir divide uma mensagem em segmentos alternados de prosa e cerca de código e resume apenas as partes de prosa, deixando os segmentos de código intactos:
// Splits text into alternating prose and code-fence segments.
// Returns [{ type: 'prose'|'code', content: string }, …]
function splitByCodeFences(text) {
const parts = [];
const re = /^```[^\n]*\n[\s\S]*?^```[ \t]*$/gm;
let lastIndex = 0;
let match;
while ((match = re.exec(text)) !== null) {
if (match.index > lastIndex) {
parts.push({
type: 'prose',
content: text.slice(lastIndex, match.index),
});
}
parts.push({ type: 'code', content: match[0] });
lastIndex = match.index + match[0].length;
}
if (lastIndex < text.length) {
parts.push({ type: 'prose', content: text.slice(lastIndex) });
}
return parts;
}
Teste a demonstração
A demonstração de compactação de sessão permite conversar com a API Prompt e compactar a sessão a qualquer momento. A barra de tokens mostra o uso do contexto em tempo real e muda de cor à medida que o contexto é preenchido. Após cada compactação, uma entrada de registro grava as contagens de tokens antes e depois para que você possa observar diretamente a redução.
É possível inspecionar o JSON de conversa completo e compactado na seção Depurar: JSON de conversa recolhível na parte de baixo da página.