1 pontos por jhs6312 6 시간 전 | Ainda não há comentários. | Compartilhar no WhatsApp

Olá. Estou criando o Spanlens, uma plataforma open source de observabilidade para ver, em um só lugar, logs de chamadas de LLM, rastreamento de custos e traces de agentes.

Por que criei isso

Ao usar LLMs em projetos paralelos pessoais, havia duas coisas que continuavam me incomodando.

Uma delas era o rastreamento de custos.
Tudo começou quando eu estava criando uma extensão de navegador baseada em GPT e me assustei pela primeira vez ao receber a fatura da OpenAI no fim do mês. Como universitário, não era um valor muito alto, mas eu via o total e não conseguia saber separadamente quanto cada funcionalidade havia custado nem quanto, em média, cada modelo estava consumindo em tokens. Então eu repetia sempre o mesmo processo: enfiava console.log no código, exportava para CSV, somava no Excel e calculava estimativas multiplicando pelos preços por modelo.

A outra era o debugging de agentes.
Foi algo que vivi na prática ao integrar o LangGraph ao Spanlens: quando um trace com várias chamadas de LLM misturadas levava 30 segundos, eu precisava abrir os logs e seguir tudo manualmente para entender

  • em qual nó o tempo estava sendo gasto
  • por que a mesma ferramenta havia sido chamada duas vezes
  • em que momento o state do LangGraph havia mudado

Criei o Spanlens para tentar reduzir esses dois problemas.

Principais recursos

  1. Integração com uma única linha de baseURL

Se você trocar o baseURL dos SDKs da OpenAI/Anthropic/Gemini para algo como https://api.spanlens.io/proxy/openai/v1, requisições, respostas, tokens e custos passam a ser registrados automaticamente. As respostas são repassadas por passthrough, então streaming, tool calling e JSON mode funcionam exatamente como no original.

Nos casos em que é necessário usar wrapping, como em agentes, disponibilizamos um SDK para injetar trace_id e span_id, de forma que as relações de pai e filho também sejam registradas.

  1. Trace de agentes + visão de topologia do LangGraph

Você pode ver o trace não apenas em uma timeline cronológica, mas também sobreposto aos nós reais do grafo. Se o agente foi construído com LangGraph, dá para ver em uma única tela em qual nó o tempo foi gasto e quais arestas são percorridas com mais frequência.

  1. Análise automática de Critical Path

A cadeia de chamadas que mais consome latência dentro de um trace é destacada automaticamente. A ideia foi reduzir o número de cliques até encontrar a resposta para a pergunta: “por que este trace ficou lento?”.

  1. Comparação estatística A/B de prompts

Compara duas versões do mesmo prompt com base em latência, custo e uso de tokens. Em vez de mostrar apenas a diferença de médias, aplica o teste t de Welch para exibir diferenças levando em conta também a variância da amostra. Incluí isso para que seja possível dizer não apenas “a média parece um pouco menor”, mas “há uma diferença significativa”.

  1. Self-hosting

Você pode subir em seu próprio servidor com uma imagem Docker. O mesmo código da versão SaaS está disponível integralmente no repositório público. Todo o código está sob licença MIT.

Como foi implementado

Atualmente, o pipeline funciona mais ou menos assim.

  • As requisições do proxy são recebidas com Hono, que separa o cabeçalho Authorization e os metadados X-Spanlens-*; a chave do provider é descriptografada com AES-256-GCM e usada apenas em memória imediatamente antes da chamada.
  • Em respostas com streaming, body.tee() devolve o stream original imediatamente ao cliente, enquanto a cópia é processada em background por um parser que calcula tokens e custos.
  • Os logs são enviados de forma assíncrona para o ClickHouse. Se o INSERT falhar, eles ficam guardados em uma fila de fallback no Supabase, e um cron faz novas tentativas. Assim, o modelo é fire-and-forget, mas tentando evitar perda de dados.
  • Os preços dos modelos ficam em uma tabela do banco e são armazenados em cache com TTL de 5 minutos usando stale-while-revalidate. Um preço de fallback funciona como rede de segurança para cold start.

No começo era apenas um proxy simples, mas ao usar na prática percebi que o mais importante não eram os logs brutos, e sim traces normalizados. Para encontrar a resposta para “por que este trace ficou lento?”, não basta a ordem das chamadas; é preciso ver relações de pai e filho, chamadas paralelas e o Critical Path. Foi daí que surgiram recursos como a visão de topologia do LangGraph e o Critical Path automático.

A stack é Next.js 14, Hono, Supabase Postgres, ClickHouse, tudo em um monorepo TypeScript com pnpm.

Pontos em que ainda estou pensando

  • Quero que o self-hosting seja possível com uma única linha de docker run, mas para isso também seria preciso incluir o Supabase Postgres. Hoje, partindo da premissa de Supabase gerenciado, o docker-compose usa 3 contêineres: web, server e ClickHouse. Estou em dúvida entre criar também uma opção de self-hosting para o Supabase ou manter a premissa de serviço gerenciado.

  • A comparação A/B de prompts já inclui o cálculo do teste t de Welch, mas ainda não decidi se vale mais a pena mostrar o p-value diretamente ou apenas um badge com a conclusão (significativo/não significativo). Também estou pensando em como exibir um aviso quando a amostra for pequena (n<30).

  • Na visão de topologia do LangGraph, nós, arestas e Critical Path são visualizados, mas deixei de fora propositalmente as mudanças no state channel porque geravam ruído demais. Gostaria de ouvir opiniões sobre se o rastreamento de mudanças de state é mais importante no debugging real ou se o nível atual está adequado.

É um projeto que começou a partir de desconfortos que vivi na prática e que venho refinando continuamente.

[ Spanlens ]
Web: https://www.spanlens.io
GitHub: https://github.com/spanlens/Spanlens
Guia de self-hosting: https://www.spanlens.io/docs/self-host

Ficarei muito grato por qualquer feedback sobre UX do dashboard, visualização de traces, forma de integração do proxy, experiência de self-hosting ou qualquer outro ponto de vista. Em especial, se houver algum provider que você gostaria que fosse suportado além de OpenAI/Anthropic/Gemini, por favor me avise nos comentários.

Há uma versão demo no site, então agradeço muito o interesse.
Atualmente a UI está em inglês, e o suporte a português também será adicionado em breve.

Ainda não há comentários.

Ainda não há comentários.