\n\n\n\n Comment otimizar o uso dos tokens com ChromaDB (passo a passo) - AgntKit \n

Comment otimizar o uso dos tokens com ChromaDB (passo a passo)

📖 12 min read2,207 wordsUpdated Mar 31, 2026

Como Otimizar a Utilização de Tokens com ChromaDB (Passo a Passo)

Se você não prestar atenção ao uso de tokens em suas consultas de banco de dados vetorial, você consumirá créditos e desempenho mais rapidamente do que imagina—portanto, aqui está como otimizar o uso de tokens com chromadb como se você realmente quisesse economizar dinheiro e tempo.

O Que Você Vai Construir e Por Que Isso É Importante

Estamos construindo um pipeline mínimo, mas eficaz, que pega documentos reais e desordenados, os armazena no ChromaDB, e os consulta com embeddings da OpenAI, enquanto minimiza o desperdício de tokens.

Pré-requisitos

  • Python 3.11+
  • pip install chroma-core==0.10.0 (última versão de março de 2026)
  • Chave API OpenAI com acesso aos endpoints de embeddings
  • Conhecimentos básicos sobre bancos de dados vetoriais e APIs de modelos de linguagem avançados

Passo 1: Configurar Seu Ambiente ChromaDB

Primeiro, você precisa instalar o ChromaDB e fazê-lo funcionar de uma maneira que se integre bem ao seu ambiente. O chroma-core, o motor principal do ChromaDB, chama muita atenção no GitHub: mais de 26.759 estrelas e 2.140 forks, então não é um simples projeto de nicho. Isso significa muita ajuda da comunidade, mas também alguns problemas abertos inevitáveis (e o ChromaDB tem 513 abertos a partir de março de 2026).

A última versão, sob a licença Apache-2.0, foi atualizada em 2026-03-21—então está sendo mantida ativamente, e isso é bom porque você vai usá-la intensamente para gerenciar seus embeddings de forma eficiente.

# Instalar chroma-core, se ainda não o fez
pip install chroma-core==0.10.0

Configurar um ChromaDB persistente significa geralmente executar este mínimo trecho de código:

from chromadb import Client

client = Client() # Usa os parâmetros padrão - SQLite + disco local
collection = client.get_or_create_collection(name="mydocs")

Por que fazer isso primeiro? Porque cada etapa seguinte gira em torno da gestão das variáveis de orçamento de tokens — e gerenciar as dependências do ChromaDB é prioridade.

Problemas comuns: Se você encontrar erros como ModuleNotFoundError, verifique suas versões. As atualizações do Chroma-core costumam alterar os internos, então fixar uma versão específica evita falhas aleatórias.

Passo 2: Fragmentar o Conteúdo para a Eficiência dos Tokens

Seus documentos não estão bem organizados—eles vêm com cabeçalhos, tabelas, notas de rodapé e elementos indesejados. Alimentar longas cadeias para as APIs de embeddings é uma maneira certa de desperdiçar tokens. Cada token conta.

Em vez disso, você fragmenta seu conteúdo de maneira inteligente. Não muito grande, não muito pequeno. Um tamanho de fragmento que corresponda ou seja ligeiramente inferior aos limites de tokens da sua API de embeddings ajuda a economizar muito em cálculos e custos desnecessários.

import tiktoken # Para a contagem de tokens, o tokenizer da OpenAI
from langchain.text_splitter import RecursiveCharacterTextSplitter

# Inicializa um divisor para chunks de aproximadamente 500 tokens (seguro para os embeddings da OpenAI)
splitter = RecursiveCharacterTextSplitter(
 chunk_size=500,
 chunk_overlap=50,
 length_function=lambda text: len(tiktoken.encoding_for_model("text-embedding-3-small").encode(text))
)

def chunk_text(text):
 chunks = splitter.split_text(text)
 print(f"Fragmentado em {len(chunks)} chunks")
 return chunks

# Exemplo de uso
doc_text = open("messy_doc.txt").read()
chunks = chunk_text(doc_text)

Por que o fragmentar economiza tokens: Se você injeta documentos completos na API de embeddings, você obtém grandes embeddings, mas principalmente ruído—além disso, você pode ultrapassar os limites de tokens ou acionar limites de taxa. Fragmentos pequenos, mas significativos, produzem de forma confiável embeddings direcionados para uma busca vetorial precisa.

Erros a serem observados: Os chunks que se sobrepõem às vezes parecem redundantes nos resultados da busca—ajuste chunk_overlap de acordo. E tenha cuidado na escolha do tokenizer. Se você usar diferentes modelos de tokenizer, suas contagens de tokens podem estar deslocadas em 20 a 30%, arruinando assim seu plano de orçamento de tokens.

Passo 3: Embeddings com ChromaDB – Otimize, Não Enterre Tudo

É aqui que muitos desenvolvedores ultrapassam seu orçamento de tokens. Passar cada fragmento pelo endpoint de embeddings da OpenAI esgota seu orçamento.

Em vez disso, você quer pré-filtrar os fragmentos antes do embedding. Use um filtro de similaridade de texto que seja econômico. Como uma verificação rápida de TF-IDF, e então embed apenas os 30–40% melhores fragmentos. Isso reduz o armazenamento, o tempo de consulta e o custo dos tokens.

from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np

# Uma aproximação econômica para filtrar chunks significativos antes de embeddings caros
def filter_chunks(chunks, query, keep_ratio=0.4):
 vectorizer = TfidfVectorizer()
 X = vectorizer.fit_transform(chunks + [query])
 query_vec = X[-1]
 chunk_vecs = X[:-1]
 similarities = (chunk_vecs @ query_vec.T).toarray().flatten()
 threshold = np.quantile(similarities, 1 - keep_ratio)
 filtered = [chunk for chunk, sim in zip(chunks, similarities) if sim >= threshold]
 print(f"Filtrado de {len(chunks)} para {len(filtered)} chunks antes do embedding")
 return filtered

chunks_to_embed = filter_chunks(chunks, "O que é a otimização do uso de tokens?")

Agora, embed somente chunks_to_embed no ChromaDB:

from openai import OpenAI
import chromadb

client = chromadb.Client()
collection = client.get_or_create_collection("mydocs")

embedding_model = OpenAI()

for chunk in chunks_to_embed:
 embedding = embedding_model.embeddings.create(input=chunk).data[0].embedding
 collection.add(
 documents=[chunk], 
 embeddings=[embedding], 
 ids=[hash(chunk) % (10 ** 8)] # ID único, mas simples
 )

Por que essa abordagem? Porque os embeddings consomem muitos tokens. Um único fragmento de 500 tokens custa 500 tokens só para ser vetorizado. Você realmente quer embedar fragmentos desnecessários? Não. Filtre de forma inteligente e economize tokens.

Erros que você pode encontrar: Limites de taxa da API. A inserção em lotes do ChromaDB pode ajudar a mitigar as chamadas da API—mais sobre isso abaixo.

Passo 4: Inserção em Lote para Reduzir Chamadas à API

Não se trata apenas de tokens—você sofre com latência e acaba pagando mais por muitas chamadas pequenas. Inserções em lotes matam dois coelhos com uma cajadada só: melhor taxa de transferência e menos chamadas API redundantes.

O método collection.add do ChromaDB suporta vários documentos & embeddings ao mesmo tempo. Agrupe seus chunks filtrados em lotes de 50 ou 100 para economizar tempo.

BATCH_SIZE = 50

def batch(iterable, n=1):
 l = len(iterable)
 for ndx in range(0, l, n):
 yield iterable[ndx:min(ndx + n, l)]

for chunk_batch in batch(chunks_to_embed, BATCH_SIZE):
 embeddings = [embedding_model.embeddings.create(input=chunk).data[0].embedding for chunk in chunk_batch]
 collection.add(
 documents=chunk_batch,
 embeddings=embeddings,
 ids=[hash(chunk) % (10 ** 8) for chunk in chunk_batch]
 )
 print(f"Indexado {len(chunk_batch)} chunks no lote")

Por que agrupar? Uma consulta = um evento de faturamento de token e um vai e vem de rede. Não seja aquele desenvolvedor que espera por 100 chamadas API individuais em fila.

Cuidado com:

  • Lotes muito grandes—mais de 100 por chamada pode te desacelerar.
  • Falhas parciais—envolva suas chamadas em try/except para gerenciar erros intermitentes, como timeouts ou 429.

Passo 5: Contagem Inteligente de Tokens Antes das Consultas — Não Advinhe

Ao executar consultas, você precisa ter uma ideia de quantos tokens todo o pipeline está queimando. Isso é crítico, especialmente se suas consultas forem longas ou uma combinação de entrada do usuário e contexto.

Em vez de adivinhar o número de tokens, confie no tiktoken ou seu equivalente para contar exatamente os tokens em cada etapa. Assim, você pode truncar ou ajustar as entradas em tempo real antes de gastar essa consulta.

def count_tokens(text, model_name="gpt-4o-mini"):
 tokenizer = tiktoken.encoding_for_model(model_name)
 tokens = tokenizer.encode(text)
 return len(tokens)

query = "Expliquez l'optimisation des tokens dans ChromaDB aussi simplement que possible."
tokens_used = count_tokens(query)
print(f"Compteur de tokens pour la requête : {tokens_used}")

Por que se dar esse trabalho? Porque as embeddings da OpenAI e as completions de chat têm limites rigorosos de tokens. Exceder 4.096 tokens geralmente provoca truncamento, erros ou taxas adicionais que você gostaria de evitar.

Erros que você encontrará: O temido OpenAIError: A extensão máxima de contexto deste modelo é de 4097 tokens. Gerencie esses erros contando os tokens antes de enviar requisições e ajustando a entrada do usuário ou o contexto (detalhado na seção seguinte).

Etapa 6: Truncamento de Contexto e Cache de Embeddings

Quando você alimenta documentos e um histórico de chat no seu modelo de linguagem, o total de tokens utilizados é de extrema importância. Um erro comum entre iniciantes é enviar sempre seu documento completo ou todo o histórico de chat sem discernimento. Você ultrapassa os limites de tokens em poucos segundos.

Sua melhor opção: truncar e armazenar em cache.

  • Armazene em cache as embeddings para documentos estáticos (não re-embedar o mesmo texto)
  • Trunque o histórico de chat de forma inteligente, priorizando as entradas recentes importantes
  • Use uma janela de tokens deslizante de cerca de 3.000 tokens para o contexto em chats/completions

Aqui está um trecho ilustrando a verificação do cache e o truncamento:

embedding_cache = {}

def get_embedding(text):
 if text in embedding_cache:
 print("Acessando o cache para a embedding")
 return embedding_cache[text]
 embedding = embedding_model.embeddings.create(input=text).data[0].embedding
 embedding_cache[text] = embedding
 return embedding

def trim_context(contexts, max_tokens=3000, model_name="gpt-4o-mini"):
 trimmed = []
 token_count = 0
 for c in reversed(contexts): # começa pelo mais recente
 tcount = count_tokens(c, model_name)
 if (token_count + tcount) <= max_tokens:
 trimmed.insert(0, c)
 token_count += tcount
 else:
 break
 print(f"Contexto reduzido para {len(trimmed)} mensagens totalizando {token_count} tokens")
 return trimmed

Essa abordagem de armazenamento em cache economiza centenas, até milhares, de tokens todos os meses.

Os Perigos

É aqui que o código ideal do tutorial encontra a realidade:

Perigo O que acontece Como evitar
Inconsistência nos limites de tokens Suas contagens de tokens estão incorretas devido a uma inconsistência entre o tokenizer ou o modelo; você ultrapassa ou usa muito poucos tokens Sempre use tiktoken.encoding_for_model() que corresponde exatamente ao modelo de embedding ou de completion que você está usando
Embeddings duplicados Embarcar o mesmo pedaço várias vezes desperdiça tokens e espaço de armazenamento Implemente o caching e o hashing dos checksums dos documentos
Erros de sobreposição de pedaços Uma sobreposição muito grande cria vetores redundantes; uma sobreposição muito pequena perde o contexto em documentos fragmentados Experimente com o parâmetro chunk_overlap, mantendo-se entre 10-15% do tamanho dos pedaços
Deadlocks de concorrência Múltiplas chamadas assíncronas para o ChromaDB ou OpenAI podem levar a condições de corrida ou inserções parciais Use código síncrono ou um bom sistema de fila assíncrona; inserções em lote o protegem disso
Contagem de tokens não confiável em textos não ingleses Os tokenizers podem contar mal devido a caracteres de múltiplos bytes ou scripts incomuns Teste com idiomas representativos, ajustando os tamanhos dos pedaços conforme necessário

Exemplo de Código Completo: Juntando Tudo

Este modelo combina todas as etapas anteriores em um pipeline funcional:

import tiktoken
from chromadb import Client
from openai import OpenAI
from langchain.text_splitter import RecursiveCharacterTextSplitter
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np

# Constantes
MODEL_NAME = "text-embedding-3-small"
EMBEDDING_BATCH_SIZE = 50
CHUNK_SIZE = 500
CHUNK_OVERLAP = 50

# Configuração
client = Client()
collection = client.get_or_create_collection(name="mydocs")
openai_client = OpenAI()
tokenizer = tiktoken.encoding_for_model(MODEL_NAME)

def count_tokens(text):
 return len(tokenizer.encode(text))

def chunk_text(text):
 splitter = RecursiveCharacterTextSplitter(
 chunk_size=CHUNK_SIZE,
 chunk_overlap=CHUNK_OVERLAP,
 length_function=count_tokens
 )
 return splitter.split_text(text)

def filter_chunks(chunks, query, keep_ratio=0.4):
 vectorizer = TfidfVectorizer()
 X = vectorizer.fit_transform(chunks + [query])
 query_vec = X[-1]
 chunk_vecs = X[:-1]
 sims = (chunk_vecs @ query_vec.T).toarray().flatten()
 thresh = np.quantile(sims, 1 - keep_ratio)
 return [chunk for chunk, sim in zip(chunks, sims) if sim >= thresh]

def batch(iterable, n=1):
 l = len(iterable)
 for ndx in range(0, l, n):
 yield iterable[ndx:min(ndx + n, l)]

def embed_and_index(chunks):
 for chunk_batch in batch(chunks, EMBEDDING_BATCH_SIZE):
 embeddings = []
 for chunk in chunk_batch:
 response = openai_client.embeddings.create(input=chunk)
 embeddings.append(response.data[0].embedding)
 ids = [str(hash(chunk) % (10**8)) for chunk in chunk_batch]
 collection.add(documents=chunk_batch, embeddings=embeddings, ids=ids)
 print(f"Lote indexado de {len(chunk_batch)} pedaços")

# Pipeline principal
doc_text = open("messy_doc.txt").read()

print("Fragmentando o documento...")
chunks = chunk_text(doc_text)
print(f"Gerados {len(chunks)} pedaços")

# Simular uma requisição de exemplo
query = "Como a utilização dos tokens é otimizada com o ChromaDB?"

print("Filtrando os pedaços antes do embedding...")
chunks_to_embed = filter_chunks(chunks, query)

print(f"Embarcando e indexando {len(chunks_to_embed)} pedaços...")
embed_and_index(chunks_to_embed)

print("Pipeline concluído.")

O que há de novo

Se você conseguiu implementar isso com sucesso, seu próximo passo deve ser integrar a recuperação classificada com as completions do GPT da OpenAI para construir um sistema de geração aumentada por recuperação (RAG) que obtém respostas da sua base de dados vetorial com custos de tokens minimizados.

Mais especificamente, concentre-se em combinar suas requisições do ChromaDB com um gerador de respostas que trunca o contexto de maneira inteligente, aplicando idealmente a reformulação das requisições para reduzir o uso de tokens na engenharia de prompts.

FAQ

P: Por que não simplesmente enviar o documento inteiro para a API de embedding de uma só vez?

R: Porque os limites de tokens da API de embedding geralmente ficam em alguns milhares de tokens — pequeno demais para grandes documentos — e você paga de forma linear por token, então você desperdiça dinheiro e obtém embeddings menos precisas que prejudicam a precisão da recuperação.

P: Como lidar com documentos que mudam com frequência no ChromaDB?

R: Você precisa implementar embeddings delta — apenas re-embarcando novos ou modificados. Uma abordagem ingênua consiste em hash de cada pedaço de texto e compará-los com os IDs armazenados para saber o que atualizar.

P: Como posso depurar erros de contagem de tokens em minha aplicação?

R: Use a biblioteca oficial tiktoken da OpenAI e certifique-se de que o nome do modelo em encoding_for_model() corresponda exatamente ao que você envia para a API. Verifique sua contagem imprimindo arrays de tokens e conferindo os tamanhos dos pedaços.

Recomendações para Diferentes Perfis de Desenvolvedores

Desenvolvedores Juniores: Comece entendendo os limites de tokens e a fragmentação. Não tente otimizar tudo ao mesmo tempo. Sua prioridade deve ser dividir os documentos em pedaços de ~500 tokens e garantir que suas chamadas de API funcionem sem erros.

Desenvolvedores de Nível Intermediário: Implemente o filtragem e agrupamento em seguida. Use o TF-IDF para pré-selecionar quais pedaços embarcar. Adicione caching para não re-embarcar duplicados. Neste estágio, você realmente economizará dinheiro e tempo.

Engenheiros Seniores: Automatize o monitoramento de tokens de ponta a ponta. Crie painéis que o alertem quando o uso aumentar. Explore segmentadores personalizados ajustados ao seu tipo de documento. Integre métricas de uso com painéis de custos e experimente com engenharia de prompts para truncamento de contexto.

Dados a partir de 22 de março de 2026. Fontes: https://github.com/chroma-core/chroma, https://community.openai.com/t/issue-chromadb-document-and-token-openai-limitations/317378

Artigos Relacionados

🕒 Published:

✍️
Written by Jake Chen

AI technology writer and researcher.

Learn more →
Browse Topics: comparisons | libraries | open-source | reviews | toolkits
Scroll to Top