Particionar texto
Divide texto em blocos semanticamente coerentes e, opcionalmente, grava cada bloco como chunk pesquisável
Você pode testar esta rota diretamente em nossa documentação interativa.
Recebe um texto bruto e devolve blocos temáticos rotulados pela IA — cada bloco é autocontido e pode ser processado separadamente sem perder contexto. Quando options.persistChunks é true, cada bloco é gravado em public.chunks com embedding no dataset escolhido, pronto para RAG.
Endpoint
POST /api/externalAPIs/public/smartSplit/partition
Parâmetros
Texto a ser particionado. Obrigatório se mediaUrls não for fornecido.
URLs de mídia (imagens, PDFs, áudio, vídeo) convertidas em texto antes do particionamento. Obrigatório se text não for fornecido; ambos podem ser enviados juntos — o texto das mídias é concatenado antes do text.
ID do host. Inferido do token quando omitido; obrigatório para tokens de master admin.
ID do avatar vinculado ao destino da persistência. Quando persistChunks: true e omitido, usa o avatar principal do host.
ID do dataset que receberá os chunks. Quando persistChunks: true e omitido, o comportamento depende de options.createDatasetIfMissing.
Quando true, cada bloco é gravado como chunk pesquisável no dataset.
Quando true e persistChunks: true sem datasetId, cria um dataset novo com nome gerado por IA. Quando false, usa o dataset mais antigo vinculado ao avatar; retorna erro se nenhum existir.
Quando true, cada bloco retorna { text, label }. Quando false, retorna { ranges, label } com intervalos [start, end] inclusivos de linhas.
Instruções livres anexadas ao prompt da IA (ex: "Agrupe por capítulo").
Modelo LLM usado no particionamento.
Provedor do modelo LLM.
Máximo de linhas por janela de sessão de IA.
Linhas repetidas entre janelas adjacentes para continuidade de contexto.
Fração mínima de linhas que precisa ser coberta (0–1).
Tamanho máximo em caracteres de cada sub-texto na pré-divisão de textos longos.
Tamanho máximo em caracteres de cada bloco gerado pelo fallback mecânico.
Quando true, a resposta inclui uncoveredLines com índices e texto das linhas fora de cobertura.
A API aceita tanto camelCase quanto snake_case nos parâmetros. text ou mediaUrls é obrigatório; ambos podem ser fornecidos simultaneamente.
Exemplos
O único campo obrigatório no body é text. Todos os outros são opcionais.
curl -X POST {{BASE_URL}}/api/externalAPIs/public/smartSplit/partition \
-H "Authorization: Bearer {{TOKEN}}" \
-H "Content-Type: application/json" \
-d '{
"text": "Chapter 1. The Beginning.\n\nOnce upon a time in a land far away, a young hero set out on a journey.\n\nChapter 2. The Challenge.\n\nThe road ahead was long. Mountains blocked the path.\n\nChapter 3. The Resolution.\n\nAfter many trials, the hero returned home, forever changed."
}'
Resposta
{
"success": true,
"blocks": [
{ "text": "Capítulo 1. O início.\n\nEra uma vez em uma terra distante...", "label": "Capítulo 1 – O início" },
{ "text": "Capítulo 2. O desafio.\n\nO caminho era longo...", "label": "Capítulo 2 – O desafio" },
{ "text": "Capítulo 3. A resolução.\n\nApós muitas provações...", "label": "Capítulo 3 – A resolução" }
],
"coverage": 1.0,
"totalLines": 9,
"sessionsUsed": 1,
"fallbackUsed": false,
"failedSessions": 0,
"reasoning": "Agrupado pelos cabeçalhos de capítulo.",
"auditLog": [
"[SmartSplit] Iniciando particionamento de texto...",
"[SmartSplit] Texto dividido em 9 linha(s)",
"[SmartSplit] 1 sessão(ões) de IA necessária(s)",
"[SmartSplit] 3 bloco(s) montado(s)",
"[SmartSplit] Cobertura: 100.0% (9/9)",
"[SmartSplit] Particionamento concluído com sucesso"
],
"persisted": null,
"uncoveredLines": { "count": 0, "indices": [], "ranges": [], "lines": [] },
"costControl": {
"usage": {
"inputTokens": 480,
"outputTokens": 95,
"totalTokens": 575,
"isEstimated": false,
"source": "smart_split_aggregate"
},
"cost": {
"inputCost": 0.000048,
"outputCost": 0.000038,
"totalCost": 0.000086,
"currency": "USD",
"pricingMissing": false,
"matchedPricingKey": "openai:gpt-4.1-nano"
},
"control": { "decision": "allow", "reasons": [] },
"references": { "caller": "smartSplit", "provider": "openai", "model": "gpt-4.1-nano" },
"reconciliation": null
}
}
Campos da Resposta
true quando a cobertura atinge o limiar e não houve erro fatal.
Blocos resultantes. O formato depende de options.returnBlocks.
Fração das linhas originais cobertas pelos blocos (0–1).
Número total de linhas do texto de entrada.
Número de sessões de IA consumidas (uma por janela deslizante).
true quando ao menos uma janela precisou usar divisão mecânica em vez de IA.
Número de janelas que retornaram 0 blocos e acionaram o fallback.
Última reasoning do modelo, quando disponível.
Rastro passo a passo do particionamento. Útil para depuração.
Presente quando options.persistChunks: true e a gravação ocorreu.
Linhas do input que não foram cobertas por nenhum bloco. Presente quando options.includeUncoveredLines: true (padrão).
Dados de consumo e custo da operação. null em erros internos.
Use options.returnBlocks: false quando precisar apenas dos intervalos de linha cobertos (útil para reprocessamento ou auditoria) em vez do texto completo do bloco.
Erros
| Código | Descrição |
|---|---|
400 | text e mediaUrls ausentes ou vazios; hostId não resolvível |
401 | Token inválido ou ausente |
500 | Falha do LLM não recuperável após fallback; erro de inserção no banco durante a persistência |
Quando a cobertura fica abaixo do limiar, a resposta volta com HTTP 200, success: false e reason: "coverage_below_threshold" junto com os blocos parciais.
Como funciona
flowchart TD
client[Cliente] -->|POST /partition| ctrl[PartitionController]
ctrl --> auth["Autenticação e resolução de hostId/avatarId/datasetId"]
auth --> media["Resolução de mídias (se mediaUrls fornecido)"]
media --> preChunk["Pré-chunking se texto > 80k chars"]
preChunk --> lines["Divisão em linhas (sentence-parse + cap 50 palavras)"]
lines --> windows["Janelas deslizantes (400 linhas, 30 overlap)"]
windows --> ia["Sessão de IA por janela"]
ia -->|0 blocos| fallback["Fallback mecânico (fallbackMaxCharsPerBlock chars/bloco)"]
ia -->|blocos| assemble
fallback --> assemble[Montar blocos e validar cobertura]
assemble -->|persistChunks true| persist["Gerar nome, criar dataset se necessário, gravar chunks"]
assemble -->|persistChunks false| shape[Shape da resposta]
persist --> shape
shape --> client
- Autenticação e resolução de contexto — o token é decodificado para extrair
hostIdeuserId. SepersistChunks: true, oavatarIde odatasetIdsão resolvidos (ou derivados do avatar principal) e validados para garantir que pertencem ao host autenticado, bloqueando acesso cross-tenant. - Resolução de mídias — quando
mediaUrlsé fornecido, cada URL (imagem, PDF, áudio, vídeo) é processada viamediaAnalysisV3e convertida em texto. O resultado é concatenado aotextantes das etapas seguintes. - Pré-chunking acima de 80 000 caracteres — textos maiores que
options.maxCharsPerChunk(padrão 80 000) são quebrados em sub-textos independentes via cortes em fronteiras naturais (parágrafo → quebra de linha → sentença). Cada sub-texto é processado separadamente e os resultados são mesclados com offset global de linhas. - Divisão em linhas — o texto é segmentado via
sentence-parse(comobserveMultipleLineBreaks: true). Linhas com mais de 50 palavras são subdivididas. Fallback para quebras de linha simples quando a biblioteca não retorna sentenças. - Janelas deslizantes — acima de
options.maxLinesPerSessionlinhas (padrão 400), o texto é cortado em janelas sobrepostas comoptions.overlapLineslinhas de overlap (padrão 30) para manter contexto entre bordas. - Sessão de IA por janela — cada janela vira uma chamada ao LLM com saída estruturada
{ blocks: [{ ranges, label }], reasoning }. O modelo retornarangesinclusivos[start, end](0-based); a expansão para índices individuais ocorre internamente. - Fallback mecânico — se a IA devolver 0 blocos (recusa, parse inválido), a janela é dividida por caracteres até
options.fallbackMaxCharsPerBlock(padrão 3 000) comlabel: null. A resposta sinaliza isso emfallbackUsedefailedSessions. - Validação de cobertura — ao final, SmartSplit checa se pelo menos
options.minCoverage(padrão0.90) das linhas foi coberta. Se não, voltasuccess: falsecomreason: "coverage_below_threshold",missingCounte os blocos parciais. Falhas de cobertura são registradas automaticamente no TypeSense para monitoramento. - Persistência opcional — quando
persistChunks: true, cada bloco é embeddado comtext-embedding-3-largee inserido empublic.chunksvinculado aodatasetId. Se odatasetIdnão foi passado ecreateDatasetIfMissing: true(padrão), aslabelsdos blocos alimentam um LLM que gera o nome do novo dataset antes da gravação. O objetopersistedna resposta trazdatasetId,avatarId,datasetCreated,datasetName(quando criado),chunkIdsecount.