Como reduzi o consumo de tokens de IA no meu workflow de Django — e transformei isso em uma ferramenta open-source
TL;DR: Arquitetei o
ciam(Context IA Manager), uma ferramenta open-source que reduz em até 90% os tokens gastos com IAs no VSCode, Cursor e Windsurf, transformando seu assistente em um agente muito mais inteligente e autônomo.
- 🧠 RAG local 100% offline (Ollama)
- 🐍 Entendimento nativo de Django (separa models, views, tasks)
- 📝 Persistência de memória: a IA não esquece seus ADRs, PRDs e bugs anteriores
- ⚡ Integração via MCP (Model Context Protocol)
Depois de uma tarde de uso intenso, o
ciampoupou 12.5k tokens reais da minha cota, entregando um contexto cirúrgico direto na IDE. A diferença entre o início e o fim da tarde (reduções de 95% para 41%) vai fazer sentido no texto.
O problema que me fez parar tudo e resolver
Trabalhando num projeto Django de médio porte — autenticação, billing Stripe, multi-tenancy, Celery — percebi um padrão ruim se repetindo todo dia:
Eu abria uma conversa com Copilot ou Claude para implementar um endpoint novo. O assistente me pedia o models.py, depois o serializers.py, depois o urls.py. Eu ia colando arquivo por arquivo. Em 10 minutos, 8k tokens de contexto consumidos antes de escrever uma linha de código. E quando a janela de contexto estourava, tinha que recomeçar.
Pior: a IA não sabia que dois commits atrás eu havia decidido usar UUID como PK, nem que tínhamos um padrão de response envelope, nem que o Celery worker rodava com acks_late=True por causa de um bug de idempotência que custou 3 horas de debug. Cada sessão começava do zero.
O gasto com tokens subia, a qualidade das respostas caía, e o que devia acelerar o desenvolvimento estava me deixando mais lento.
A inspiração: th0th
Encontrei o th0th — um projeto em TypeScript/Node.js que resolve exatamente esse problema com busca semântica e compressão de contexto. A ideia central é poderosa:
Em vez de enviar arquivos inteiros para a IA, indexe o projeto e sirva apenas os chunks relevantes para cada pergunta.
O artigo original aqui no TabNews mostra reduções de 98% com essa abordagem. Mas eu queria algo diferente:
- Binário único sem Node.js como dependência
- Consciência nativa de Django — entender a diferença entre um
models.pye umviews.pye categorizar na hora da busca - Memória persistente entre projetos — decisões que tomei no projeto A devem estar acessíveis no projeto B
- Métricas reais de economia de tokens, não estimativas
- Indexação incremental — só re-embeda o que mudou
Então reescrevi do zero em Go e chamei de ciam. A CLI em si é um binário rápido que não "suja" o setup com dependências pesadas de runtime, enquanto orquestra por baixo dos panos (via ciam up) a stack RAG local (Ollama) usando Docker, mantendo seu código 100% privado.
Como o ciam funciona
A arquitetura é intencionalmente simples:
VSCode / Cursor / Antigravity
│ MCP stdio
▼
ciam mcp server ──HTTP──▶ ciam API (:8080) ──▶ Ollama (:11434)
│
▼
SQLite (~/.local/share/ciam/ciam.db)
Três componentes:
- ciam API (Go, Docker) — indexa, gera embeddings via Ollama, armazena no SQLite, serve buscas
- ciam MCP server (Go, stdio) — traduz chamadas do assistente em requisições HTTP para a API
- ciam CLI —
ciam index .,ciam search,ciam watch,ciam status
O modelo de embedding é o nomic-embed-text rodando no Ollama — offline, gratuito, boa qualidade para código.
O que ajustei além do básico
1. Indexador ciente de Django
O chunk genérico coloca todo código no mesmo balde. O indexador Django categoriza automaticamente:
models.py → chunk_type: model
views.py → chunk_type: view
serializers.py → chunk_type: serializer
urls.py → chunk_type: url
tasks.py → chunk_type: task
conftest.py → chunk_type: test
signals.py → chunk_type: signal
A categorização usa duas estratégias: primeiro o nome do arquivo, depois heurísticas de conteúdo (from django.db import models, ModelSerializer, @shared_task). O resultado é que você pode filtrar a busca:
ciam search "autenticação" --type model
ciam search "envio de email" --type task
ciam search "permissão de acesso" --type view
2. Busca híbrida com RRF
Só embeddings não bastam — palavras exatas como nomes de campos e classes ficam mal rankeadas em busca puramente semântica. O ciam implementa Reciprocal Rank Fusion combinando cosine similarity (vetorial) com BM25 (keyword), a mesma estratégia descrita no th0th:
score_final = Σ 1 / (60 + rank_vetorial) + Σ 1 / (60 + rank_BM25)
Na prática: ciam search "LeadCapture model" encontra o model correto mesmo que a query seja parcialmente exata e parcialmente semântica.
3. Indexação incremental por arquivo
O problema do re-index completo: num projeto com 200+ arquivos Python, te re-embedar tudo a cada mudança é lento e desperdicia GPU. O ciam resolve com hash SHA-256 por arquivo:
POST /api/v1/project/file
{ project_id, file_hash, chunks[] }
Servidor: if stored_hash == file_hash → skip (zero embeddings gerados)
Resultado: só o arquivo que mudou é re-embedado. O banco não perde o histórico dos outros arquivos.
4. ciam watch — indexação em tempo real
ciam watch . # polling a cada 2s
ciam watch . --interval 5
[14:23:01] ✓ leads/models.py (model, 3 chunks)
[14:23:07] ✓ docs/plans/plan-002-billing.md (plan, 1 chunk)
[14:23:09] ✓ payments/serializers.py (serializer, 2 chunks)
Deixa rodando em background enquanto você desenvolve. Quando o assistente perguntar sobre LeadCapture, ele já está indexado — sem precisar rodar ciam index . manualmente.
5. Gestão de conhecimento: ADR, PRD e Planos
Código é o como. A IA também precisa do porquê e do o quê. O ciam incorpora um sistema de conhecimento direto na CLI:
# Antes de iniciar uma feature
ciam prd new "Sistema de billing via Stripe"
# → cria docs/prd/PRD-001-sistema-de-billing-via-stripe.md
# → indexa automaticamente (searchable agora)
ciam plan new "Integração Stripe" --prd PRD-001
# → cria docs/plans/Plan-001-integracao-stripe.md
# → indexa automaticamente
# Antes de fazer um fix relevante
ciam adr new "Fix: race condition no worker de emails"
# → cria docs/adr/ADR-001-...md
# → indexa automaticamente
O ponto chave: ao criar o documento, ele é indexado imediatamente. Quando você pedir para o assistente "implementar a fase 2 do plano Stripe", ele lê o PRD, o plano e o código relevante em uma única chamada MCP (ciam_decision_context).
6. Memória persistente entre sessões
ciam remember "UsarUUID como PK em todos os models — decidido para facilitar merges entre ambientes"
ciam remember "Celery workers com acks_late=True — bug de idempotência corrido em março" --type bug
ciam remember "padrão de response: { data, meta, errors } em todos os endpoints" --type decision
Esses registros ficam num banco separado, com embedding próprio. Quando o assistente chama ciam_recall "UUID", recupera o contexto mesmo meses depois, em qualquer projeto.
O resultado em números — honesto
Vou mostrar dois snapshots reais do ciam status, tirados com horas de diferença:
Snapshot 1 — primeiros testes (uso pontual, poucas buscas):
Token savings:
Project size (est.): ~29104 tokens
Served via search: 1240 tokens
Reduction: ~95% fewer tokens to the AI
Estimated saved: ~27864 tokens total
95%. Impressionante. Mas honestamente, eram só 5 buscas. A IA foi cirúrgica — cada pergunta trouxe exatamente o chunk certo.
Snapshot 2 — depois de uma tarde de uso intenso (25+ chamadas MCP reais):
Token savings:
Project size (est.): ~30821 tokens
Served via search: 18315 tokens
Reduction: ~41% fewer tokens to the AI
Estimated saved: ~12506 tokens total
Projects:
PROJECT CHUNKS FILES ~TOKENS TYPES
autosaas 32 5 13110 generic:17 view:15
context-ia-manager 18 4 5772 generic:18
backend 19 14 8188 model:2 url:5 form:1...
docs 10 2 3744 generic:10
MCP tool usage:
FERRAMENTA CHAMADAS LAT.MÉD.
ciam_search 13 480ms
ciam_context 5 123ms
ciam_decision_context 2 986ms
ciam_recall 2 284ms
ciam_adr_search 1 310ms
ciam_plan_search 1 1603ms
ciam_remember 1 444ms
ciam_index 1 4ms
ciam_django_map 1 35ms
A redução caiu para 41% — e isso é a melhor notícia possível.
Pensa assim: o projeto tem ~30k tokens. Se eu tivesse colado arquivos na mão nessas 25+ chamadas — mesmo só 3 arquivos por chamada, 2k tokens cada — seriam 150k+ tokens consumidos. O ciam serviu 18.3k tokens total em todas as buscas somadas.
O ciam status mede redução de uma forma conservadora: tokens servidos ÷ tamanho total do índice. Mas o denominador correto é tokens que teriam sido consumidos sem ciam. Com uso intenso, essa diferença real fica ainda maior — o índice cresce O(n), o consumo sem ciam cresce O(n × número de perguntas).
A redução real no dia a dia é próxima de 90%+ — o número do status simplesmente não captura isso porque compara com uma única leitura completa, não com N leituras repetidas.
O que a IA ganha com o MCP
Quando o VSCode abre um projeto com .vscode/mcp.json, o assistente tem acesso a 12 ferramentas:
| Ferramenta | Quando usar |
|---|---|
ciam_route | Não sabe qual tool chamar? Descreve em linguagem natural, recebe a tool certa + params |
ciam_search | Busca genérica de código |
ciam_context | Busca + comprime em uma chamada (token máximo) |
ciam_django_map | Mapa estrutural: apps → models → views → urls |
ciam_adr_search | Por que essa decisão foi tomada? |
ciam_prd_search | O que esse endpoint precisa fazer? |
ciam_plan_search | Como está organizada a implementação? |
ciam_research_search | Pesquisas externas relevantes ingeridas no projeto |
ciam_decision_context | Tudo em uma chamada: código + ADR + PRD + plans |
ciam_remember | Armazena decisão na memória persistente |
ciam_recall | Recupera memórias de sessões anteriores |
ciam_compress | Comprime código: mantém assinaturas, remove docstrings |
ciam_index | Re-indexa o projeto via MCP |
O ciam_decision_context é o mais poderoso: antes de implementar qualquer coisa, o assistente chama essa ferramenta e recebe em um único request — os chunks de código mais relevantes, os ADRs que impactam a decisão, os requisitos do PRD e o plano de implementação. Tudo comprimido.
O ciam_route é o que mais mudou meu jeito de usar: em vez de eu decidir qual tool chamar, passo a intenção em português e o servidor devolve {"tool": "ciam_decision_context", "params": {...}, "reason": "..."}. Isso significa que o assistente nunca fica travado escolhendo entre 13 ferramentas.
Install em 3 comandos
Pré-requisitos: Go 1.22+ instalado localmente e Docker.
git clone https://github.com/smkbarbosa/context-ia-manager
cd context-ia-manager
make install # instala o binário ciam em ~/go/bin
# Sobe Ollama + ciam API
ciam up
# No seu projeto Django:
cd /seu/projeto
ciam init # auto-detecta seu editor (VSCode, Cursor, Windsurf, etc.) e gera a config MCP
ciam index . # indexa e categoriza tudo
ciam watch . # deixa em background para re-index automático
# Pronto — abra seu editor e o assistente já tem contexto
O que vem a seguir
ciam watchcom inotify — troca o polling por eventos reais do FS no Linux- Dashboard web — a página
/statusjá existe; expandir com gráficos de economia por projeto - Suporte a FastAPI e GenericPython — o indexador Django já diferencia tipos; replicar para outros frameworks
ciam research— comando para ingerir artigos/PDFs externos como contexto pesquisável
Por que vale testar
Se você usa GitHub Copilot, Claude ou qualquer IA com contexto limitado no seu workflow Django, o ciam resolve três coisas ao mesmo tempo:
- Gasta menos tokens — a IA recebe só o que precisa para cada pergunta
- Respostas mais precisas — contexto cirúrgico bate contexto bruto
- Memória real — decisões de arquitetura, bugs corrigidos e requisitos de produto ficam acessíveis entre sessões e entre projetos
O projeto é open-source, roda 100% offline, e você vê a economia em tempo real com ciam status.
→ github.com/smkbarbosa/context-ia-manager
Se a ideia faz sentido pro seu workflow, considere deixar uma estrela (⭐) no repositório! E caso use a ferramenta, sinta-se à vontade para abrir uma Issue com melhorias (como expandir o indexador para FastAPI/Flask) ou comentar aqui com o impacto em tokens mostrado pelo seu ciam status. Estou muito curioso para ver a redução real em outros projetos.