<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cleber Lucas</title>
    <description>The latest articles on DEV Community by Cleber Lucas (@obelucca__).</description>
    <link>https://dev.to/obelucca__</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3394098%2Fec93f9b6-6118-4efe-92b6-c139478cdfd8.webp</url>
      <title>DEV Community: Cleber Lucas</title>
      <link>https://dev.to/obelucca__</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/obelucca__"/>
    <language>en</language>
    <item>
      <title>Do help desk ao código: o que o suporte técnico me ensinou sobre ser um dev melhor</title>
      <dc:creator>Cleber Lucas</dc:creator>
      <pubDate>Thu, 30 Jul 2026 17:22:19 +0000</pubDate>
      <link>https://dev.to/obelucca__/do-help-desk-ao-codigo-o-que-o-suporte-tecnico-me-ensinou-sobre-ser-um-dev-melhor-1ac4</link>
      <guid>https://dev.to/obelucca__/do-help-desk-ao-codigo-o-que-o-suporte-tecnico-me-ensinou-sobre-ser-um-dev-melhor-1ac4</guid>
      <description>&lt;p&gt;Antes de escrever a primeira linha de código pensando em produção, eu já sabia escutar. Não é força de expressão: durante anos, minha rotina foi ouvir gente frustrada com um sistema travado, um financeiro que não fechava ou uma rede que caía na hora errada. Hoje, como Desenvolvedor Júnior, percebo que boa parte da minha atenção a detalhes, aos logs, aos critérios de aceite e, principalmente, ao usuário do outro lado da tela, vem exatamente dali.&lt;/p&gt;

&lt;p&gt;Esse texto é sobre essa trajetória — e sobre como o suporte, muitas vezes tratado como "porta de entrada menor" na carreira de tecnologia, na verdade me deu ferramentas que uso todos os dias como dev.&lt;/p&gt;

&lt;h2&gt;
  
  
  O início: vendendo tecnologia sem saber que era tecnologia
&lt;/h2&gt;

&lt;p&gt;Minha história em TI não começou com programação. Começou aos 18 anos, na &lt;strong&gt;Two Side Connection&lt;/strong&gt;, uma startup fundada por um amigo e mentor, Pedro Lara. Eu fui o primeiro contratado e, por consequência, o "faz tudo" da empresa.&lt;/p&gt;

&lt;p&gt;A plataforma que vendíamos era voltada para escritórios de arquitetura, unificando orçamento, fornecedores e relacionamento com clientes em um só lugar. Comecei vendendo, mas rapidamente a realidade de startup me puxou para outros papéis: implantação do sistema nos clientes, gestão de uma equipe de suporte e participação em reuniões de vendas e parcerias.&lt;/p&gt;

&lt;p&gt;Foi ali, no meio do caos organizado de uma empresa em crescimento, que a tecnologia despertou meu interesse de verdade. Quando a Two Side foi vendida, tive que decidir o que fazer da vida. Vendas não era o caminho. Comecei a estudar programação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Escolpi Informática: minha primeira base técnica de verdade
&lt;/h2&gt;

&lt;p&gt;A porta de entrada oficial no mercado de tecnologia foi uma vaga de &lt;strong&gt;Suporte Técnico na Escolpi Informática&lt;/strong&gt;, empresa que desenvolvia e vendia sistemas de PDV, controle de estoque e financeiro para supermercados e pequenos negócios.&lt;/p&gt;

&lt;p&gt;Foi lá que tive meu primeiro contato sério com consultas SQL, manutenção de hardware e suporte a sistemas em Java. E foi lá também que criei algo que hoje reconheço como meu primeiro "produto interno": uma Wiki de base de conhecimento, onde toda a equipe podia registrar e consultar soluções para problemas recorrentes do sistema.&lt;/p&gt;

&lt;p&gt;Sem saber, eu já estava documentando processos e pensando em escalabilidade de conhecimento — só que a "stack" ainda era outra.&lt;/p&gt;

&lt;h2&gt;
  
  
  A furada que valeu a pena: Flix Promotora
&lt;/h2&gt;

&lt;p&gt;Nem toda experiência precisa ser um case de sucesso para ensinar algo. Meu estágio na &lt;strong&gt;Flix Promotora&lt;/strong&gt;, uma empresa de call center, foi curto e, sinceramente, não recomendo nem o produto nem o modelo de trabalho de lá. Minha função era manutenção de hardware, sem muito espaço para crescer.&lt;/p&gt;

&lt;p&gt;Mas foi lá que conheci meu gestor, Adriano, que depois me ajudou a conseguir uma vaga no &lt;strong&gt;Colégio São José&lt;/strong&gt;. Às vezes a experiência ruim não é sobre o que você aprende tecnicamente, mas sobre quem você conhece no caminho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Colégio São José: infraestrutura, boas práticas e os profissionais que me inspiraram
&lt;/h2&gt;

&lt;p&gt;No Colégio São José Escolápias, atuando como Analista de TI, tive a sorte de trabalhar ao lado de dois profissionais que, apesar de mais jovens que eu, tinham uma visão de tecnologia muito acima da média: &lt;strong&gt;Rafael&lt;/strong&gt; e &lt;strong&gt;João&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Em seis meses, Rafael transformou completamente a forma como o colégio lidava com tecnologia: segurança, boas práticas de TI e integração de sistemas com o TOTVS para áreas críticas como matrícula, financeiro, contábil e RH. Eu tive o privilégio de participar desse processo — padronizando os computadores das salas de aula, implementando TVs para apoiar os professores nas aulas e melhorando toda a rede do colégio.&lt;/p&gt;

&lt;p&gt;João, por sua vez, trabalhava a implementação gradativa de GPOs, controlando o acesso e a informação que chegava aos computadores da sala de informática.&lt;/p&gt;

&lt;p&gt;Foi um período de aprendizado técnico real, mas também de referência profissional: ver dois jovens conduzindo uma transformação de infraestrutura inteira com tanta competência me mostrou o padrão que eu queria alcançar.&lt;/p&gt;

&lt;h2&gt;
  
  
  South Tecnologia: de analista de infraestrutura a criador de soluções
&lt;/h2&gt;

&lt;p&gt;A relação construída no Colégio São José me abriu a porta para a &lt;strong&gt;South Tecnologia&lt;/strong&gt;, como Analista de Infraestrutura, ao lado de Braulio e Matheus. Ali, prestávamos suporte terceirizado de infraestrutura para diversas empresas do grupo: Premium Clube, Plamev Pet, Meep, Tá Rastreado, Pronto Assistência, Essential — entre outras.&lt;/p&gt;

&lt;p&gt;Com tantas empresas para atender, via chat e presencialmente, a equipe cresceu rápido. E foi esse crescimento que me fez enxergar oportunidades de melhoria — não pedidas, mas necessárias.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O bot de chamados.&lt;/strong&gt; Como usávamos o Discord como canal principal, tive a ideia de transformá-lo em interface de abertura de chamados. A pessoa enviava um resumo com empresa, solicitante, descrição do problema e como foi resolvido. O bot, integrado à IA do Gemini, devolvia o chamado já formatado, pronto para colar direto no GLPI. Um problema operacional resolvido com uma ideia simples de automação.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O agente RAG para os POPs.&lt;/strong&gt; Com o crescimento da equipe, o SLA começou a subir. Por fazer parte do time desde o início, eu era constantemente procurado por colegas para tirar dúvidas sobre processos já documentados — e tínhamos cerca de 90 POPs, muitos deles cheios de detalhes que nem eu mesmo conhecia de cor. A solução foi criar um &lt;strong&gt;agente RAG&lt;/strong&gt; treinado com essa base de conhecimento. Bastava mandar uma mensagem no Discord para receber a resposta certa, reduzindo drasticamente o tempo de atendimento.&lt;/p&gt;

&lt;p&gt;Foi esse projeto — nascido de uma dor real de suporte — que me abriu a oportunidade de me tornar &lt;strong&gt;desenvolvedor&lt;/strong&gt; na South Tecnologia. Comecei em projetos da Plamev, depois atuei como front-end no Tá Rastreado e no AEasy, um produto voltado para associações.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que o suporte me ensinou sobre ser dev
&lt;/h2&gt;

&lt;p&gt;Se tem um ponto central nessa trajetória toda, é este: &lt;strong&gt;atuar em suporte me formou como desenvolvedor antes mesmo de eu escrever código profissionalmente.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alguns motivos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Escuta ativa das dores do usuário.&lt;/strong&gt; Suporte é, o tempo todo, ouvir o que não está funcionando na visão de quem usa. Isso me deu uma visão de produto que muitos devs só desenvolvem depois de anos — a de pensar pelo lado de quem vai usar o que estou construindo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentação como hábito, não como tarefa extra.&lt;/strong&gt; Registrar chamados com o máximo de contexto possível, para poder escalonar quando necessário, me ensinou a valorizar informação clara e completa — algo que hoje aplico em issues, PRs e specs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atenção a logs e erros.&lt;/strong&gt; Trabalho repetitivo em suporte parece cansativo, mas treina um olho fino para padrões, causas raiz e sintomas — exatamente o que se precisa para debugar bem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visão resolutiva.&lt;/strong&gt; Suporte não aceita "não sei", porque alguém do outro lado está travado. Essa urgência saudável virou parte de como encaro bugs e bloqueios hoje.
No fim, cada chamado atendido, cada POP escrito, cada usuário ouvido foi, sem que eu percebesse na hora, um treino silencioso para o tipo de desenvolvedor que eu queria ser: alguém atento, resolutivo e que nunca perde de vista quem está do outro lado do sistema.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Você também veio de suporte ou infraestrutura para o desenvolvimento? Como essa experiência mudou a forma como você programa hoje? Bora trocar ideia nos comentários.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>php</category>
      <category>suporte</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Usando o Claude como um recrutador técnico pessoal para encontrar minha próxima vaga</title>
      <dc:creator>Cleber Lucas</dc:creator>
      <pubDate>Mon, 27 Jul 2026 20:47:33 +0000</pubDate>
      <link>https://dev.to/obelucca__/usando-o-claude-como-um-recrutador-tecnico-pessoal-para-encontrar-minha-proxima-vaga-154k</link>
      <guid>https://dev.to/obelucca__/usando-o-claude-como-um-recrutador-tecnico-pessoal-para-encontrar-minha-proxima-vaga-154k</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Percebi que gastava mais tempo procurando vagas do que realmente me candidatando.&lt;/p&gt;

&lt;p&gt;Todo fim de tarde era a mesma rotina: abrir o Indeed, digitar "desenvolvedor PHP", rolar dezenas de resultados quase idênticos, abrir cinco ou seis em novas abas, ler a descrição, comparar mentalmente com meu currículo e, na maioria das vezes, fechar a aba sem me candidatar porque "não parecia ser bem o meu perfil". No dia seguinte, repetir.&lt;/p&gt;

&lt;p&gt;O problema nunca foi encontrar vagas. Era descobrir quais realmente valiam meu tempo.&lt;/p&gt;

&lt;p&gt;Depois de algumas semanas nesse ciclo, cheguei a uma pergunta meio óbvia, mas que eu ainda não tinha levado a sério: e se a IA pudesse atuar como um recrutador técnico? Não como um gerador de currículo genérico, e sim como alguém que primeiro entende profundamente quem eu sou tecnicamente, depois sai atrás de vagas reais, e só então me diz "essa aqui vale a pena, e é por isso".&lt;/p&gt;

&lt;p&gt;Foi exatamente esse fluxo que construí. Neste artigo conto como ele nasceu, o que ele fez com o meu currículo real, e por que o resultado final — uma planilha ranqueada com score, justificativa e recomendações — mudou completamente a forma como eu busco emprego.&lt;/p&gt;

&lt;h1&gt;
  
  
  O problema
&lt;/h1&gt;

&lt;p&gt;Buscar vaga de forma manual tem uma armadilha que ninguém avisa: parece produtivo, mas na prática é um teatro de produtividade.&lt;/p&gt;

&lt;p&gt;Alguns motivos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Volume sem filtro.&lt;/strong&gt; Uma busca simples como "desenvolvedor PHP" retorna centenas de resultados. A maioria pede um perfil de PHP diferente do meu — outro framework, outra escala de projeto, outra senioridade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aderência baixa e invisível.&lt;/strong&gt; Você só descobre se a vaga combina com você depois de ler a descrição inteira — e mesmo assim, é uma avaliação no "achismo".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ATS como caixa-preta.&lt;/strong&gt; Sistemas de triagem automática descartam currículos por não conterem as palavras-chave certas, mesmo quando o candidato tem a experiência necessária. Uma vaga de PHP que pede "CodeIgniter" descarta na triagem quem só cita "PHP MVC" no currículo, mesmo que a experiência seja equivalente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Candidaturas repetitivas.&lt;/strong&gt; Enviar o mesmo currículo genérico para vagas de PHP com contextos bem diferentes — uma focada em fintech, outra em e-commerce, outra em automação com IA — é ineficiente e, pior, sinaliza falta de adequação para quem recruta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custo de oportunidade.&lt;/strong&gt; Cada hora gasta lendo vagas ruins é uma hora que poderia ter sido usada estudando, praticando entrevista ou refinando um projeto do portfólio.
No meu caso específico, isso ficava ainda mais evidente porque meu perfil de PHP não é "padrão de prateleira". Tenho quase dois anos de experiência formal em desenvolvimento, mas também mais de dois anos em suporte e infraestrutura de TI antes disso. Meu dia a dia com PHP 8 em arquitetura MVC anda junto com React/Next.js no frontend e uma camada de IA aplicada (RAG, LLMs) que não é tão comum em vagas de PHP júnior. Um filtro raso de palavra-chave simplesmente não capturava essa combinação — e eu não queria me candidatar para qualquer vaga de PHP, e sim para as que realmente aproveitassem esse conjunto todo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eu precisava de alguém — ou de alguma coisa — capaz de olhar para esse conjunto de experiências como um todo e cruzar isso, vaga por vaga, com o que realmente estava sendo pedido no mercado.&lt;/p&gt;

&lt;h1&gt;
  
  
  A ideia
&lt;/h1&gt;

&lt;p&gt;O fluxo que desenhei tem uma lógica bem simples no papel, mas que muda tudo na prática: a IA só pode procurar vagas depois de entender profundamente quem eu sou tecnicamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Currículo
  ↓
Análise de Perfil (senioridade, stack, pontos fortes, lacunas)
  ↓
Detecção de Gaps Técnicos
  ↓
Busca de Vagas no Indeed
  ↓
Score de Aderência por Vaga
  ↓
Otimização de Currículo
  ↓
Candidatura
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada etapa resolve um problema específico:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Currículo → Análise de Perfil.&lt;/strong&gt; Antes de qualquer busca, a IA precisa "conhecer" o candidato com profundidade — não só listar tecnologias, mas entender nível de senioridade, projetos de destaque e o tipo de experiência que sustenta cada afirmação do currículo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detecção de Gaps.&lt;/strong&gt; Toda vaga boa também expõe uma lacuna. Saber disso com antecedência evita ser pego de surpresa na entrevista e ajuda a preparar uma resposta honesta em vez de fingir domínio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Busca no Indeed.&lt;/strong&gt; Só depois desse contexto pronto a IA sai para pesquisar vagas reais, recentes, e com informações completas (empresa, local, modalidade, stack, link).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score de Aderência.&lt;/strong&gt; Cada vaga recebe uma nota justificada — não um "sim ou não" binário, mas um raciocínio explícito do porquê aquele score.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Otimização de Currículo.&lt;/strong&gt; Para as vagas mais bem ranqueadas, a IA sugere quais projetos destacar, quais palavras-chave usar e como reorganizar o currículo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Candidatura.&lt;/strong&gt; A etapa humana. A IA prepara o material, mas quem aperta o botão e vai para a entrevista sou eu.
# O Prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Não vou colar o prompt inteiro aqui — ele é longo e específico demais para ser reaproveitado copiando e colando. Mas vale explicar a lógica por trás das partes mais importantes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Primeiro, obriguei a IA a entender quem eu era
&lt;/h2&gt;

&lt;p&gt;Antes de procurar qualquer vaga, o primeiro bloco do prompt pedia uma análise estruturada do meu currículo, cobrindo pontos como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analise o currículo anexado e retorne:
- Senioridade adequada (com justificativa)
- Principais tecnologias (separadas por frontend, backend, dados, devops, IA)
- Experiências relevantes
- Projetos de destaque e o que cada um comprova
- Pontos fortes reais (não genéricos)
- Lacunas técnicas prováveis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O motivo de pedir isso antes de tudo é simples: se a IA não souber que eu tenho experiência com dois backends diferentes, ou que meu projeto de fintech (Quita) prova domínio de arquitetura multi-tenant e conformidade com LGPD, ela vai avaliar cada vaga de forma rasa, olhando só para bater ou não bater palavra-chave.&lt;/p&gt;

&lt;h2&gt;
  
  
  Depois, transformei essa análise em critério de busca
&lt;/h2&gt;

&lt;p&gt;A segunda parte do prompt usava esse perfil já analisado como filtro para a pesquisa de vagas, com instruções explícitas de que tipo de vaga trazer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Com base no perfil analisado, busque vagas recentes no Indeed para Desenvolvedor PHP que:
- sejam compatíveis com o nível de senioridade identificado
- exijam PHP como linguagem central (MVC, CodeIgniter, Laravel ou equivalente)
- considerem também stacks complementares do candidato (React, PostgreSQL, IA aplicada)
- tenham informações completas (empresa, local, modalidade, link)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  E por fim, pedi justificativa, não só nota
&lt;/h2&gt;

&lt;p&gt;A parte que fez mais diferença no resultado final foi obrigar a IA a justificar cada score, e não apenas cuspir um número:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Para cada vaga, calcule um score de aderência de 0 a 100% e explique:
- por que esse score e não outro
- quais tecnologias da vaga o candidato já possui
- quais projetos ele deve destacar nessa vaga específica
- quais palavras-chave usar no currículo
- pontos fracos e como compensá-los na candidatura
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse detalhe muda tudo. Um score sem explicação é só um número que você tem que confiar cegamente. Um score com justificativa vira uma ferramenta de decisão.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resultado
&lt;/h1&gt;

&lt;p&gt;O resultado da primeira etapa foi, honestamente, mais revelador do que eu esperava.&lt;/p&gt;

&lt;p&gt;A IA classificou minha senioridade como "júnior avançado / transição para pleno", justificando com o tempo de experiência formal em desenvolvimento somado à bagagem anterior em suporte e infraestrutura — um raciocínio que eu mesmo tinha dificuldade de verbalizar em entrevistas.&lt;/p&gt;

&lt;p&gt;Nas lacunas, ela foi direta: pouca exposição documentada a Kubernetes, arquitetura orientada a eventos (Lambda, SQS/SNS), testes automatizados em larga escala e ferramentas de observabilidade, além de nenhuma certificação formal em nuvem. Nada que eu não suspeitasse, mas ver isso escrito com clareza ajuda a priorizar o que estudar em seguida, em vez de estudar "um pouco de tudo".&lt;/p&gt;

&lt;p&gt;Na busca de vagas, o resultado foi uma planilha com colunas de título, empresa, localização, modalidade, tecnologias exigidas, score de aderência, justificativa, link oficial e recomendações de candidatura. Filtrando pelas vagas que realmente pediam PHP como linguagem central, o ranking ficou assim:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Posição&lt;/th&gt;
&lt;th&gt;Vaga&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Desenvolvedor(a) React, PHP ou Fullstack — Advisorh Talent Solutions&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Programador PHP Back-end — Why Digital&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Desenvolvedor(a) Backend (PHP + IA aplicada) — SOM VIBE&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A vaga da Advisorh ficou em primeiro não por ser a "mais impressionante" no papel, mas porque foi a de menor atrito real entre o meu currículo e o requisito: ela aceita explicitamente as duas frentes que já exerço no dia a dia (PHP e React/TypeScript), sem exigir anos mínimos de experiência formal.&lt;/p&gt;

&lt;p&gt;O que mais me chamou atenção foi o nível de detalhe nas justificativas. Na vaga da Why Digital, a análise notou que a descrição mencionava "rastreamento veicular" e sugeriu reaproveitar um discurso que eu já tinha preparado para uma candidatura anterior parecida — algo que eu jamais lembraria sozinho no meio de dezenas de abas abertas. Já na vaga da SOM VIBE, a IA conectou diretamente meu projeto de agente RAG (POPS_AI) com o requisito de "IA aplicada" da vaga, mesmo ela sendo, no fim das contas, uma vaga de PHP.&lt;/p&gt;

&lt;p&gt;Isso é muito melhor do que buscar vaga manualmente porque elimina o viés de "acho que essa vaga é boa para mim" e substitui por "essa vaga é boa para você por estes motivos específicos, e aqui está o que fazer a respeito".&lt;/p&gt;

&lt;h1&gt;
  
  
  Segunda etapa
&lt;/h1&gt;

&lt;p&gt;Com o ranking pronto, usei a IA novamente — mas dessa vez para gerar currículos personalizados para cada vaga de PHP mais bem posicionada.&lt;/p&gt;

&lt;p&gt;O motivo é simples: mesmo dentro de um único alvo — "vaga de PHP" — um currículo único não funciona igual para todas as oportunidades. Minha experiência com PHP aparece em contextos bem diferentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PHP puro, foco em manutenção de produto SaaS&lt;/strong&gt; — o caso da Advisorh, que pede React/TypeScript ou PHP em produto já em produção.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP com integrações e sistemas legados&lt;/strong&gt; — o caso da Why Digital, com APIs REST/SOAP e projetos de rastreamento veicular.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP combinado com automação e IA aplicada&lt;/strong&gt; — o caso da SOM VIBE, onde PHP divide protagonismo com n8n e integrações de IA.
Para a vaga da Advisorh, o currículo gerado abriu com a atuação simultânea em PHP 8 (MVC) e React/TypeScript na South Ti, citando o Quita como prova de domínio fullstack completo com integração de APIs REST. Para a Why Digital, o destaque foi outro: PHP 8, integração de sistemas e o discurso já preparado sobre rastreamento veicular, com menos ênfase em frontend. Já para a SOM VIBE, o currículo trouxe para o topo o POPS_AI e as integrações com Gemini/OpenAI do Quita, exatamente porque "IA aplicada" era um requisito explícito da vaga — mesmo o cargo sendo, no fundo, uma vaga de PHP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cada versão manteve os mesmos fatos — não inventei nada — mas reordenou a ênfase, trocou os termos técnicos que abrem cada bullet e priorizou o projeto certo para o contexto certo. É o tipo de trabalho que, feito manualmente para três ou quatro vagas diferentes, consome uma tarde inteira. Automatizado, levou minutos, e o mais importante: com justificativa explícita de por que cada mudança foi feita.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lições aprendidas
&lt;/h1&gt;

&lt;p&gt;Depois de rodar esse processo algumas vezes, ficaram claras algumas coisas.&lt;/p&gt;

&lt;p&gt;A primeira é que a IA não substitui um recrutador humano — ela elimina o trabalho repetitivo que normalmente consome o tempo que você deveria estar usando para se preparar de verdade. Ler cem vagas, comparar cada uma com seu perfil, calcular mentalmente aderência: isso é trabalho mecânico, não julgamento humano.&lt;/p&gt;

&lt;p&gt;A segunda é que ela ajuda na tomada de decisão, mas não decide por você. O score de 90% da vaga da Advisorh foi um ótimo ponto de partida, mas a decisão de se candidatar, de como se posicionar na entrevista e de negociar proposta continua sendo minha.&lt;/p&gt;

&lt;p&gt;A terceira, e talvez a mais importante: entrevistas continuam humanas. Nenhuma IA vai simular a pressão de uma sala (ou chamada de vídeo) com um entrevistador do outro lado perguntando por que você tomou determinada decisão de arquitetura. O que esse fluxo faz é garantir que você chegue até essa entrevista pelo motivo certo — porque a vaga realmente combina com você — em vez de chegar lá por sorte estatística de ter mandado currículo para cinquenta lugares.&lt;/p&gt;

&lt;p&gt;Também vale registrar uma lição mais prática: a qualidade do resultado depende diretamente da qualidade da análise inicial. Se a etapa de "conhecer o candidato" for rasa, todo o resto do fluxo — busca, score, currículo — herda essa rasez. Foi por isso que a primeira etapa do prompt recebeu tanta atenção quanto todas as outras juntas.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;A IA não encontrou um emprego para mim. Ela encontrou as oportunidades certas.&lt;/p&gt;

&lt;p&gt;Continua sendo eu quem participa das entrevistas, quem negocia e quem decide aceitar ou não uma proposta. Mas o tempo que eu gastava rolando páginas de resultados genéricos agora vai para estudar exatamente as lacunas que a própria análise apontou, e para chegar em cada entrevista sabendo exatamente por que aquela vaga faz sentido para mim — e por que eu faço sentido para ela.&lt;/p&gt;

&lt;p&gt;Se você também está numa busca ativa por vaga de PHP (ou de qualquer outra stack): como você tem usado IA nesse processo? Já tentou automatizar a análise de aderência entre currículo e vaga, ou ainda faz tudo manualmente? Tenho muita curiosidade de saber se outras pessoas chegaram a fluxos parecidos — ou completamente diferentes — para resolver o mesmo problema.&lt;/p&gt;

</description>
      <category>php</category>
      <category>carreira</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Build a Collaborative Mindset with AI (and How It Helped Me Build Quita)</title>
      <dc:creator>Cleber Lucas</dc:creator>
      <pubDate>Tue, 07 Jul 2026 19:29:33 +0000</pubDate>
      <link>https://dev.to/obelucca__/how-to-build-a-collaborative-mindset-with-ai-and-how-it-helped-me-build-quita-448n</link>
      <guid>https://dev.to/obelucca__/how-to-build-a-collaborative-mindset-with-ai-and-how-it-helped-me-build-quita-448n</guid>
      <description>&lt;p&gt;While taking Google's AI Fundamentals course, I ran into a topic that sounds simple but completely changes how you work with AI day to day: &lt;strong&gt;collaborative mindset&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Treating AI as a development partner means handing it context, direction, and technical feedback in order to get something useful back, the same way a junior teammate would need clear guidance to deliver good work.&lt;/p&gt;

&lt;p&gt;I understood this in practice while building &lt;strong&gt;Quita&lt;/strong&gt;, my tool that helps people interpret credit reports from Brazil's Central Bank (Registrato) and automatically generate formal complaints on Consumidor.gov.br, on top of real architectural and backend decisions. I want to share what I learned, with a stronger focus on how to specify requirements better and how I used collaboration with AI as part of my own technical learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with talking to AI the wrong way
&lt;/h2&gt;

&lt;p&gt;A lot of people treat AI like an oracle: they ask little, expect a lot, and get frustrated when the answer comes back generic, incomplete, or flat-out wrong. The issue usually isn't the tool, it's how the conversation was framed.&lt;/p&gt;

&lt;p&gt;When I started building Quita, I noticed that the vaguer my prompts were, the vaguer the answers I got back. The turning point was realizing that collaborating with AI is a two-way process: I need to bring technical clarity, and only then can the AI bring precision.&lt;/p&gt;

&lt;h2&gt;
  
  
  A clear picture of what the system needs to do
&lt;/h2&gt;

&lt;p&gt;Before asking for a single line of code, I needed to be able to describe Quita's data flow in technical terms, not in pitch-deck terms. The system receives a payload from a Registrato query, needs to normalize that data into a consistent internal format, identify inconsistencies between values reported by different institutions, and generate a structured text that follows the schema accepted by Consumidor.gov.br.&lt;/p&gt;

&lt;p&gt;When I describe the flow this way, with clear input, transformation, and output, the AI stops filling gaps with assumptions and starts proposing solutions within the system's real constraints. A vague specification produces generic code. A technical specification, with an explicit data flow, produces a solution aligned with the architecture that already exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  A defined audience is also a technical requirement
&lt;/h2&gt;

&lt;p&gt;Quita is used by people with no familiarity with financial or legal jargon. That sounds like a UX detail, but in practice it becomes a technical requirement: API error messages, the text generated by AI inside the complaints, and even the structure of the JSON responses the frontend consumes all need to carry that consideration.&lt;/p&gt;

&lt;p&gt;When I state this explicitly in prompts (for example, when asking for the structure of an endpoint that returns a credit analysis result), the suggestions for field naming, validation messages, and response format shift accordingly. A well-defined audience acts as a filter that narrows the AI's interpretation space at every layer of the system, from the database up to the interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  A well-scoped problem is what cuts hallucination the most
&lt;/h2&gt;

&lt;p&gt;This is the core point I already suspected before the course confirmed it: the more scoped the problem, the less room the AI has to invent a solution.&lt;/p&gt;

&lt;p&gt;Asking "help me improve my credit system" is too vague. The AI will fill the gaps with assumptions, and assumptions produce hallucination. Asking "given the JSON returned by the Registrato query, with the fields already defined in my DTO, the system needs to identify inconsistencies between values reported by different institutions and generate a complaint text following the structure accepted by Consumidor.gov.br" is a problem with clear edges: known input, explicit comparison rule, defined output format. The AI has no reason to invent anything, because the response space is already shaped by the specification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowing the basics of your stack isn't optional
&lt;/h2&gt;

&lt;p&gt;This is something I only learned through practice: collaborating well with AI requires that I understand, at least at a basic level, every piece of what I'm building. Without that, there's no way to judge whether the answer I got is correct, or to ask for something more specific in the next round.&lt;/p&gt;

&lt;p&gt;Quita's architecture today looks like this: a Java 21 backend with Spring Boot and Spring Security for JWT-based authentication, PostgreSQL with Flyway managing migrations, all running in production on Railway. The frontend is Next.js with TypeScript and Tailwind, deployed on Vercel, consuming the API through authenticated calls. The AI layer (Gemini and OpenAI) sits as an internal backend service, receiving already-normalized credit report data and returning the structured complaint text.&lt;/p&gt;

&lt;p&gt;Understanding this architecture, even at the level of "what talks to what," is what gave me the autonomy to catch the AI's mistakes instead of accepting them. A few concrete examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When configuring CORS between the frontend on Vercel and the backend on Railway, I got a suggestion that allowed origin &lt;code&gt;*&lt;/code&gt; alongside &lt;code&gt;credentials: true&lt;/code&gt;, a combination the browser itself rejects. I only caught it because I already knew how CORS handles that combination.&lt;/li&gt;
&lt;li&gt;In a suggested Flyway migration, the AI proposed altering a column without accounting for data already present in the production table, which would have broken the deploy. Understanding how Flyway versions and applies migrations is what made me review it before running it.&lt;/li&gt;
&lt;li&gt;In a Gemini API integration, I got a code example using a parameter from an outdated SDK version. Without knowing the basics of how that call should be structured, I would have copied and pasted it without noticing it wouldn't even compile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these cases required deep expertise. They required just enough to be suspicious, test, and ask again. That "just enough" is exactly what a collaborative mindset assumes: you don't need to know everything, but you need to know enough to not accept an answer just because it sounds coherent.&lt;/p&gt;

&lt;p&gt;This also changes the quality of the question I ask. Understanding the basics of authentication leads me to ask "how do I validate this JWT in the Next.js middleware without breaking server-side rendering," instead of simply "how do I build login." A more specific question produces a more specific answer, and a more specific answer leaves less room for hallucination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business context and external rules also guard against hallucination
&lt;/h2&gt;

&lt;p&gt;It's not just code. Quita operates under rules that come from the outside: the Bacen data format, the structural requirements of Consumidor.gov.br. When I bring those rules explicitly into the conversation with the AI, not just the technical requirement, the chance of getting a solution that's technically correct but useless in practice drops significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using AI collaboration to learn while building
&lt;/h2&gt;

&lt;p&gt;This was the most valuable takeaway from the whole process: a collaborative mindset can be used deliberately to learn, not just to ship faster.&lt;/p&gt;

&lt;p&gt;There's a real technical difference between asking "implement JWT token validation" and asking "explain how JWT validation works in this middleware, then implement it." The first approach hands you a ready-to-paste solution. The second hands you the reasoning behind it, which lets me maintain, debug, and extend that code on my own afterward, without depending on going back to the AI for every adjustment.&lt;/p&gt;

&lt;p&gt;That's how I picked up things while building Quita that I ended up applying directly to the architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why Flyway versions migrations sequentially and treats them as immutable, and why altering a migration already applied in production is considered bad practice, which changed how I plan schema changes.&lt;/li&gt;
&lt;li&gt;Why a short-lived JWT access token is paired with a longer-lived refresh token, and how that balances security with user experience without forcing constant logins.&lt;/li&gt;
&lt;li&gt;Why browsers enforce the same-origin policy and exactly when CORS kicks in, which finally resolved the recurring errors in the Vercel-to-Railway integration.&lt;/li&gt;
&lt;li&gt;How to structure prompts for the Gemini API to get consistent JSON output, which required understanding a bit about how the model handles structured formatting versus free text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these started as a practical Quita problem and turned into knowledge I now carry into the next technical decision, even outside the project. It creates a loop: the more I understand, the better I frame the next question; the better the question, the more precise the answer; and the more precise the answer, the more I learn from it.&lt;/p&gt;

&lt;p&gt;The risk in this process is learning shallowly, accepting code without understanding why it works. The way I guard against that is simple: before accepting any solution beyond the trivial, I ask the AI to explain the "why" behind the chosen approach, not just the "how" to implement it. If the explanation doesn't make sense to me, that's a sign I need to understand the concept better before putting that code into production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iteration is part of the process, not a sign of failure
&lt;/h2&gt;

&lt;p&gt;Quita's design system, the "Da névoa à rota" (From the fog to the route) concept, built around glassmorphism and forest green as the primary color, didn't come out finished on the first try. It went through several rounds of adjustment with AI, each one refining the visual identity a little further. Understanding that the first answer is just a draft, not the final delivery, took the pressure off "getting it right on the first try" and actually improved the end result.&lt;/p&gt;

&lt;h2&gt;
  
  
  You're still the one in control
&lt;/h2&gt;

&lt;p&gt;Collaborating doesn't mean delegating blindly. Every code suggestion, every generated text, every design decision the AI proposed for Quita went through my own review before reaching production. AI speeds up the process, but the responsibility for the final result still belongs to the developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collaborative mindset as a working method
&lt;/h2&gt;

&lt;p&gt;In the end, what I learned building Quita is that collaborating with AI looks a lot like guiding a talented junior teammate who doesn't know your context: you need to bring a clear specification, a defined audience, a scoped problem, real architecture, and at least a baseline of technical knowledge to recognize when something's off. In return, the payoff isn't just delivery speed, it's technical learning accumulated with every round of conversation.&lt;/p&gt;

&lt;p&gt;Quita is in production today because each of these pieces, clear technical specification, defined audience, scoped problem, explicit architecture, human review, and continuous learning, worked together. Not because I asked the AI to "build a credit analysis system" and got a finished solution back.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>architecture</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Como ter mentalidade colaborativa com a IA (e como isso me ajudou a construir o Quita)</title>
      <dc:creator>Cleber Lucas</dc:creator>
      <pubDate>Tue, 07 Jul 2026 19:28:13 +0000</pubDate>
      <link>https://dev.to/obelucca__/como-ter-mentalidade-colaborativa-com-a-ia-e-como-isso-me-ajudou-a-construir-o-quita-1a36</link>
      <guid>https://dev.to/obelucca__/como-ter-mentalidade-colaborativa-com-a-ia-e-como-isso-me-ajudou-a-construir-o-quita-1a36</guid>
      <description>&lt;p&gt;Durante o curso de Fundamentos de IA do Google, cheguei num tema que parece simples, mas muda completamente a forma como você trabalha com inteligência artificial no dia a dia: &lt;strong&gt;mentalidade colaborativa&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Tratar a IA como parceira de desenvolvimento significa entregar contexto, direção e feedback técnico pra receber algo útil de volta, do jeito que um colega júnior de time precisaria de orientação clara pra entregar um trabalho bom.&lt;/p&gt;

&lt;p&gt;Foi construindo o &lt;strong&gt;Quita&lt;/strong&gt;, minha ferramenta que ajuda pessoas a interpretarem relatórios de crédito do Banco Central (Registrato) e gerarem reclamações automáticas no Consumidor.gov.br, que entendi isso na prática, em cima de decisões técnicas reais de arquitetura, backend e integração com IA. Quero compartilhar o que aprendi, com foco maior em como especificar melhor e em como usei a colaboração com a IA como parte do meu próprio aprendizado técnico.&lt;/p&gt;

&lt;h2&gt;
  
  
  O problema de conversar mal com a IA
&lt;/h2&gt;

&lt;p&gt;Muita gente trata a IA como um oráculo: pergunta pouco, espera muito, e se frustra quando a resposta vem genérica, incompleta ou simplesmente errada. O erro geralmente não está na ferramenta, está na forma como a conversa foi conduzida.&lt;/p&gt;

&lt;p&gt;Quando comecei a desenvolver o Quita, percebi que quanto mais eu jogava perguntas soltas pra IA, mais eu recebia respostas soltas de volta. O ponto de virada foi entender que colaborar com IA é um processo de duas mãos: eu preciso trazer clareza técnica, e só assim a IA consegue trazer precisão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visão clara do que o sistema precisa fazer
&lt;/h2&gt;

&lt;p&gt;Antes de pedir qualquer linha de código, eu precisava conseguir descrever o fluxo de dados do Quita em termos técnicos, não em termos de pitch. O sistema recebe um payload de consulta do Registrato, precisa normalizar esses dados num formato interno consistente, identificar inconsistências entre os valores reportados por diferentes instituições, e gerar um texto estruturado que siga o schema aceito pelo Consumidor.gov.br.&lt;/p&gt;

&lt;p&gt;Quando descrevo esse fluxo assim, com entrada, transformação e saída bem definidas, a IA para de preencher lacunas com suposições e começa a propor soluções dentro dos limites reais do sistema. Especificação vaga gera código genérico. Especificação técnica, com fluxo de dados explícito, gera solução alinhada com a arquitetura que já existe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Público definido também é um requisito técnico
&lt;/h2&gt;

&lt;p&gt;O Quita é usado por pessoas que não têm familiaridade com jargão financeiro ou jurídico. Isso parece um detalhe de UX, mas na prática vira requisito técnico: as mensagens de erro da API, os textos gerados pela IA nas reclamações, e até a estrutura das respostas JSON que o frontend consome precisam carregar esse cuidado.&lt;/p&gt;

&lt;p&gt;Quando informo isso explicitamente pra IA nos prompts (por exemplo, ao pedir a estrutura de um endpoint que retorna o resultado da análise de crédito), as sugestões de nomenclatura de campos, mensagens de validação e formato de resposta mudam. Público bem definido funciona como um filtro que reduz o espaço de interpretação da IA em cada camada do sistema, do banco de dados até a interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problema bem delimitado é o que mais reduz alucinação
&lt;/h2&gt;

&lt;p&gt;Esse é o ponto central que eu já intuía antes mesmo do curso confirmar: quanto mais delimitado o problema, menos espaço a IA tem para inventar solução.&lt;/p&gt;

&lt;p&gt;Pedir "ajuda a melhorar meu sistema de crédito" é vago demais. A IA vai preencher as lacunas com suposições, e suposições geram alucinação. Pedir "a partir do JSON retornado pela consulta do Registrato, com os campos que já defini no meu DTO, o sistema precisa identificar inconsistências entre valores reportados por diferentes instituições e gerar um texto de reclamação seguindo a estrutura aceita pelo Consumidor.gov.br" é um problema com bordas claras: entrada conhecida, regra de comparação explícita, saída num formato definido. A IA não tem motivo pra inventar nada, porque o espaço de resposta já está desenhado pela especificação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saber o básico da stack técnica não é opcional
&lt;/h2&gt;

&lt;p&gt;Esse é um aprendizado que só veio com a prática: colaborar bem com a IA exige que eu também entenda, ainda que no básico, cada peça do que estou construindo. Sem isso, não dá pra avaliar se a resposta que recebi está certa, nem pra pedir algo mais específico na próxima rodada.&lt;/p&gt;

&lt;p&gt;A arquitetura do Quita hoje é essa: backend em Java 21 com Spring Boot e Spring Security pra autenticação via JWT, banco PostgreSQL com Flyway controlando as migrations, tudo rodando em produção no Railway. O frontend é Next.js com TypeScript e Tailwind, publicado na Vercel, consumindo a API via chamadas autenticadas. A camada de IA (Gemini e OpenAI) entra como serviço interno do backend, recebendo os dados já normalizados do relatório de crédito e devolvendo o texto estruturado da reclamação.&lt;/p&gt;

&lt;p&gt;Entender essa arquitetura, mesmo que no nível de "o que conversa com o quê", foi o que me deu autonomia pra identificar erros da IA em vez de aceitá-los. Alguns exemplos concretos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ao configurar CORS entre o frontend na Vercel e o backend no Railway, recebi sugestões de configuração que liberavam origem &lt;code&gt;*&lt;/code&gt; junto com &lt;code&gt;credentials: true&lt;/code&gt;, uma combinação que o próprio navegador rejeita. Só percebi o problema porque já sabia como o CORS trata essa combinação.&lt;/li&gt;
&lt;li&gt;Numa sugestão de migration do Flyway, a IA propôs alterar uma coluna sem considerar dados já existentes na tabela em produção, o que quebraria o deploy. Entender como o Flyway versiona e aplica migrations foi o que me fez revisar antes de rodar.&lt;/li&gt;
&lt;li&gt;Em uma integração com a API do Gemini, recebi um exemplo de código usando um parâmetro de um SDK desatualizado. Sem conhecer o básico de como a chamada deveria se estruturar, eu teria copiado e colado sem perceber que aquilo não compilaria.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nenhum desses casos exigiu expertise profunda. Exigiu o suficiente pra desconfiar, testar e perguntar de novo. É esse "suficiente" que a mentalidade colaborativa pressupõe: você não precisa saber tudo, mas precisa saber o bastante pra não aceitar qualquer resposta só porque ela parece coerente.&lt;/p&gt;

&lt;p&gt;Isso também muda a qualidade da pergunta que eu faço. Entender o básico de autenticação me leva a perguntar "como validar esse token JWT no middleware do Next.js sem quebrar o server-side rendering", em vez de simplesmente "como fazer login". Pergunta mais específica gera resposta mais específica, e resposta mais específica tem menos espaço pra alucinação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contexto de negócio e regras externas também blindam contra alucinação
&lt;/h2&gt;

&lt;p&gt;Não é só código. O Quita opera sobre regras que vêm de fora: o formato de dados do Bacen, as exigências de estrutura do Consumidor.gov.br. Quando trago essas regras explicitamente pra conversa com a IA, e não só o requisito técnico, a chance de receber uma solução tecnicamente correta, mas inútil na prática, cai bastante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Colaborar com a IA como forma de aprender enquanto desenvolve
&lt;/h2&gt;

&lt;p&gt;Esse foi o aprendizado mais valioso do processo todo: a mentalidade colaborativa pode ser usada deliberadamente para aprender, não só pra produzir mais rápido.&lt;/p&gt;

&lt;p&gt;Existe uma diferença técnica relevante entre pedir "implemente a validação do token JWT" e pedir "explique como funciona a validação de um JWT nesse middleware, e só depois implemente". A primeira forma entrega uma solução pronta pra colar. A segunda entrega o raciocínio por trás dela, o que me permite manter, depurar e estender aquele código sozinho depois, sem depender de voltar pra IA a cada ajuste.&lt;/p&gt;

&lt;p&gt;Foi assim que aprendi, construindo o Quita, coisas que fui aplicando direto na arquitetura:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Por que o Flyway versiona migrations de forma sequencial e imutável, e por que alterar uma migration já aplicada em produção é considerado prática ruim, o que mudou como eu planejo alterações de schema.&lt;/li&gt;
&lt;li&gt;Por que um access token JWT de vida curta é combinado com um refresh token de vida mais longa, e como isso equilibra segurança e experiência do usuário sem exigir login constante.&lt;/li&gt;
&lt;li&gt;Por que o navegador aplica a política de mesma origem e quando exatamente o CORS entra em ação, o que resolveu de vez os erros recorrentes na integração entre a Vercel e o Railway.&lt;/li&gt;
&lt;li&gt;Como estruturar prompts pra API do Gemini de forma a obter uma saída em JSON consistente, o que exigiu entender um pouco de como o modelo lida com formatação estruturada versus texto livre.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cada um desses pontos começou como um problema prático do Quita e virou conhecimento que eu carrego pra próxima decisão técnica, mesmo fora do projeto. Isso cria um ciclo: quanto mais eu entendo, melhor formulo a próxima pergunta; quanto melhor a pergunta, mais precisa a resposta; e quanto mais precisa a resposta, mais eu aprendo com ela.&lt;/p&gt;

&lt;p&gt;O risco desse processo é aprender de forma rasa, aceitando o código sem entender por que ele funciona. A forma como me protejo disso é simples: antes de aceitar qualquer solução mais complexa, peço pra IA explicar o "porquê" da abordagem escolhida, não só o "como" implementar. Se a explicação não faz sentido pra mim, é sinal de que preciso entender melhor o conceito antes de colocar aquele código em produção.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iteração faz parte do processo, não é sinal de erro
&lt;/h2&gt;

&lt;p&gt;O design system do Quita, o conceito "Da névoa à rota", com glassmorphism e verde floresta como cor primária, não nasceu pronto. Passou por várias rodadas de ajuste com a IA, cada uma refinando um pouco mais a identidade visual. Entender que a primeira resposta é só um rascunho, não a entrega final, tirou a pressão de "acertar de primeira" e trouxe mais qualidade pro resultado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Você continua no controle
&lt;/h2&gt;

&lt;p&gt;Colaborar não é delegar cegamente. Cada sugestão de código, cada texto gerado, cada decisão de design que a IA propôs pro Quita passou por revisão minha antes de ir pra produção. A IA acelera o processo, mas a responsabilidade pelo resultado final continua sendo do desenvolvedor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mentalidade colaborativa como método de trabalho
&lt;/h2&gt;

&lt;p&gt;No fim, o que aprendi construindo o Quita é que colaborar com IA se parece com orientar um colega júnior talentoso, mas que não conhece o seu contexto: é preciso trazer especificação clara, público, problema delimitado, arquitetura real e um mínimo de conhecimento técnico pra reconhecer quando algo sai fora do esperado. Em troca, o ganho não é só velocidade de entrega, é aprendizado técnico acumulado a cada rodada de conversa.&lt;/p&gt;

&lt;p&gt;O Quita está em produção hoje porque cada uma dessas peças, especificação técnica clara, público definido, problema delimitado, arquitetura explícita, revisão humana e aprendizado contínuo, trabalhou junto. Não porque pedi pra IA "criar um sistema de análise de crédito" e recebi de volta uma solução pronta.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>softwarearchitetcure</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Quita: How a Personal Problem Became a Real Product — and What I Learned Along the Way</title>
      <dc:creator>Cleber Lucas</dc:creator>
      <pubDate>Mon, 22 Jun 2026 15:58:42 +0000</pubDate>
      <link>https://dev.to/obelucca__/quita-how-a-personal-problem-became-a-real-product-and-what-i-learned-along-the-way-5a3a</link>
      <guid>https://dev.to/obelucca__/quita-how-a-personal-problem-became-a-real-product-and-what-i-learned-along-the-way-5a3a</guid>
      <description>&lt;p&gt;There's a piece of advice you hear constantly in the developer world: "build projects to learn." The problem is that most portfolio projects are born without a real pain behind them. And without real pain, there's no motivation to go deep, to solve the hard problem, to push through when things break.&lt;/p&gt;

&lt;p&gt;Quita was born differently. It was born from a genuine need.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Nobody Solves Simply
&lt;/h2&gt;

&lt;p&gt;I spent a few years carrying debt accumulated during a rougher phase of life. When I finally had the financial stability to deal with it, I went looking for answers — what exactly was outstanding, with whom, and what the law guaranteed me as a consumer.&lt;/p&gt;

&lt;p&gt;What I found was a maze.&lt;/p&gt;

&lt;p&gt;The information existed — in the Central Bank of Brazil, on the Consumidor.gov.br platform, in consumer protection legislation. But the path to accessing and using it was confusing enough to make anyone give up. Almost everything I found through searches pointed to law firms or paid consultancies. Services that charge to do something that, in theory, any citizen can do on their own.&lt;/p&gt;

&lt;p&gt;I started thinking: if I — someone with access to information and some familiarity with technology — had difficulty navigating this, what happens to those who don't?&lt;/p&gt;

&lt;p&gt;Brazil has decades of consumer debt history. Millions of people who can't renegotiate their debts not just because of lack of money, but because of lack of clear guidance on what to do, where to start, and what rights they have.&lt;/p&gt;

&lt;p&gt;That's when Quita started making sense.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Quita Is
&lt;/h2&gt;

&lt;p&gt;Quita is a digital assistant built for the indebted citizen.&lt;/p&gt;

&lt;p&gt;It guides users from obtaining their financial reports from the Central Bank of Brazil — the Registrato, a document that consolidates all debts registered in the financial system — all the way to generating structured complaints for Consumidor.gov.br, the platform where financial institutions are legally required to respond.&lt;/p&gt;

&lt;p&gt;The core flow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user uploads their Registrato PDF&lt;/li&gt;
&lt;li&gt;The system automatically extracts the debts listed in the document&lt;/li&gt;
&lt;li&gt;Insights are generated about the debt situation — amounts, institutions, current status&lt;/li&gt;
&lt;li&gt;Based on this data, Quita uses AI to produce a well-founded regulatory complaint, ready to be submitted to the responsible institution
The goal isn't to solve the debt for the user. It's to give them clear information and a concrete instrument to exercise their rights on their own terms.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;The project was built with a modern, deliberately lean stack focused on productivity and reliability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 21&lt;/li&gt;
&lt;li&gt;Spring Boot 4&lt;/li&gt;
&lt;li&gt;Spring Security with JWT authentication&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Flyway (database migrations)&lt;/li&gt;
&lt;li&gt;Maven
&lt;strong&gt;Frontend&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;Framer Motion
&lt;strong&gt;Artificial Intelligence&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Google Gemini (regulatory complaint generation)&lt;/li&gt;
&lt;li&gt;OpenAI (fallback layer and experimentation)
&lt;strong&gt;Infrastructure&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Railway (backend and database hosting)&lt;/li&gt;
&lt;li&gt;Vercel (frontend hosting — in deployment)
&lt;strong&gt;Payments&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Mercado Pago
&lt;strong&gt;Other&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;PDF extraction and processing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - LGPD compliance: the PDF is processed in memory and deleted after extraction
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Approach That Changed Everything: Specification-Driven Development
&lt;/h2&gt;

&lt;p&gt;If there's one technical lesson I want to highlight from this journey, it's not about any particular technology.&lt;/p&gt;

&lt;p&gt;It's about process.&lt;/p&gt;

&lt;p&gt;Most of Quita was built through SDDs — Software Design Documents. Before writing any line of code, I wrote the intent. I defined what the system should do, why, what the constraints were, the flows, the expected behaviors at the edges.&lt;/p&gt;

&lt;p&gt;This habit transformed the quality of what I built.&lt;/p&gt;

&lt;p&gt;When you specify before you implement, the questions that surface are different. You start asking about the user, about risks, about what happens when something goes wrong. You find ambiguities before they become bugs.&lt;/p&gt;

&lt;p&gt;AI entered this process not as a code generator, but as an analysis partner. I would present a specification and question it together: is this clear? Is there a case I haven't covered? Does this decision make sense given this context?&lt;/p&gt;

&lt;p&gt;In many moments, the work was more about thinking than programming.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Working in Production Today
&lt;/h2&gt;

&lt;p&gt;The backend is live on Railway. All core features have been validated end-to-end:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User registration and JWT authentication&lt;/li&gt;
&lt;li&gt;Registrato PDF upload and processing&lt;/li&gt;
&lt;li&gt;Automatic debt extraction&lt;/li&gt;
&lt;li&gt;Insight generation&lt;/li&gt;
&lt;li&gt;AI-powered complaint generation via Gemini&lt;/li&gt;
&lt;li&gt;Complaint export as PDF
The frontend is in its final integration phase, with deployment planned on Vercel.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's Coming Next
&lt;/h2&gt;

&lt;p&gt;The next delivery is the first functional public version — with a complete web interface, full integration with the production backend, and the complete flow accessible to real users.&lt;/p&gt;

&lt;p&gt;After that, the roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Guided onboarding for new users&lt;/li&gt;
&lt;li&gt;Expanded support for additional document types&lt;/li&gt;
&lt;li&gt;Refinement of the complaint generation model&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Exploring monetization viability
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What This Project Taught Me
&lt;/h2&gt;

&lt;p&gt;Fictional projects teach syntax. Real projects teach you to think like an engineer.&lt;/p&gt;

&lt;p&gt;The difference is in the pressure a real problem creates. When you know there's someone on the other side who can be helped, every decision carries weight. You don't skip steps. You don't accept a solution that only works on the happy path.&lt;/p&gt;

&lt;p&gt;And perhaps the most honest lesson from this journey is that AI doesn't replace software engineering. It amplifies it. When you know what you want to build, when you have clarity about the problem, AI accelerates. When you don't, it just generates confusion faster.&lt;/p&gt;

&lt;p&gt;Quita isn't finished yet. But it's closer than ever.&lt;/p&gt;

&lt;p&gt;And it was built to solve a real problem, with real technology, for real people.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>saas</category>
      <category>java</category>
      <category>ai</category>
    </item>
    <item>
      <title>Quita: como um problema pessoal virou um produto real — e o que aprendi no caminho</title>
      <dc:creator>Cleber Lucas</dc:creator>
      <pubDate>Mon, 22 Jun 2026 15:49:55 +0000</pubDate>
      <link>https://dev.to/obelucca__/quita-como-um-problema-pessoal-virou-um-produto-real-e-o-que-aprendi-no-caminho-2lm6</link>
      <guid>https://dev.to/obelucca__/quita-como-um-problema-pessoal-virou-um-produto-real-e-o-que-aprendi-no-caminho-2lm6</guid>
      <description>&lt;p&gt;Tem uma frase que ouço muito no mundo do desenvolvimento: "construa projetos para aprender". O problema é que a maioria dos projetos de portfólio nasce sem uma dor real por trás. E sem dor real, falta motivação para ir fundo, para resolver o problema difícil, para não desistir quando trava.&lt;/p&gt;

&lt;p&gt;O Quita nasceu diferente. Nasceu de uma necessidade verdadeira.&lt;/p&gt;




&lt;h2&gt;
  
  
  O problema que ninguém resolve de forma simples
&lt;/h2&gt;

&lt;p&gt;Passei alguns anos com dívidas acumuladas de uma fase mais turbulenta da vida. Quando finalmente tive condição financeira de resolver isso, fui atrás de entender o que estava em aberto, com quem, e o que a lei me garantia como consumidor.&lt;/p&gt;

&lt;p&gt;O que encontrei foi um labirinto.&lt;/p&gt;

&lt;p&gt;As informações existiam — no Banco Central, no Consumidor.gov.br, na legislação. Mas o caminho para acessá-las e usá-las era confuso o suficiente para fazer qualquer pessoa desistir. Quase tudo que encontrava nas buscas levava para escritórios de advocacia ou consultorias pagas. Serviços que cobram para fazer algo que, em tese, o próprio cidadão pode fazer sozinho.&lt;/p&gt;

&lt;p&gt;Comecei a pensar: se eu, com acesso a informação e alguma familiaridade com tecnologia, tive dificuldade nisso, o que acontece com quem não tem?&lt;/p&gt;

&lt;p&gt;O Brasil tem décadas de histórico de superendividamento. Milhões de pessoas que não conseguem renegociar suas dívidas não apenas por falta de dinheiro, mas por falta de orientação clara sobre o que fazer, por onde começar, quais direitos têm.&lt;/p&gt;

&lt;p&gt;Foi aí que o Quita começou a fazer sentido.&lt;/p&gt;




&lt;h2&gt;
  
  
  O que é o Quita
&lt;/h2&gt;

&lt;p&gt;O Quita é um assistente digital voltado para o cidadão endividado.&lt;/p&gt;

&lt;p&gt;Ele guia o usuário desde a obtenção dos relatórios financeiros junto ao Banco Central — o Registrato, documento que consolida todas as dívidas registradas no sistema financeiro — até a geração de manifestações estruturadas para o Consumidor.gov.br, plataforma onde as instituições financeiras são legalmente obrigadas a responder.&lt;/p&gt;

&lt;p&gt;O fluxo principal é:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;O usuário faz upload do PDF do Registrato&lt;/li&gt;
&lt;li&gt;O sistema extrai automaticamente as dívidas presentes no documento&lt;/li&gt;
&lt;li&gt;São gerados insights sobre o endividamento — valores, instituições, situação&lt;/li&gt;
&lt;li&gt;Com base nesses dados, o Quita produz, via IA, uma reclamação regulatória fundamentada, pronta para ser enviada à instituição responsável
O objetivo não é resolver a dívida pelo usuário. É dar a ele informação clara e um instrumento concreto para exercer seus direitos por conta própria.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  A stack técnica
&lt;/h2&gt;

&lt;p&gt;O projeto foi construído com uma stack moderna e deliberadamente enxuta, com foco em produtividade e confiabilidade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 21&lt;/li&gt;
&lt;li&gt;Spring Boot 4&lt;/li&gt;
&lt;li&gt;Spring Security com autenticação JWT&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Flyway (migrations)&lt;/li&gt;
&lt;li&gt;Maven
&lt;strong&gt;Frontend&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;TypeScript
&lt;strong&gt;Inteligência Artificial&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Google Gemini (geração de reclamações regulatórias)&lt;/li&gt;
&lt;li&gt;OpenAI (camada de fallback e experimentação)
&lt;strong&gt;Infraestrutura&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Railway (hospedagem do backend e banco de dados)&lt;/li&gt;
&lt;li&gt;Vercel (hospedagem do frontend — em implantação)
&lt;strong&gt;Outros&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Extração e processamento de PDFs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Conformidade com LGPD: o PDF é processado em memória e removido após a extração
&lt;/h2&gt;

&lt;h2&gt;
  
  
  A abordagem que mudou tudo: desenvolvimento guiado por especificação
&lt;/h2&gt;

&lt;p&gt;Se há um aprendizado técnico que quero destacar dessa jornada, não é sobre nenhuma tecnologia em particular.&lt;/p&gt;

&lt;p&gt;É sobre processo.&lt;/p&gt;

&lt;p&gt;Grande parte do Quita foi construída através de SDDs — Software Design Documents. Antes de escrever qualquer linha de código, eu escrevia a intenção. Definia o que o sistema deveria fazer, por quê, quais eram as restrições, os fluxos, os comportamentos esperados nas bordas.&lt;/p&gt;

&lt;p&gt;Esse hábito transformou a qualidade do que eu construí.&lt;/p&gt;

&lt;p&gt;Quando você especifica antes de implementar, as perguntas que surgem são diferentes. Você se pergunta sobre o usuário, sobre os riscos, sobre o que acontece quando algo dá errado. Você descobre ambiguidades antes que elas virem bugs.&lt;/p&gt;

&lt;p&gt;A IA entrou nesse processo não como geradora de código, mas como parceira de análise. Eu apresentava uma especificação e questionava junto: isso está claro? Existe algum caso que não cobri? Essa decisão faz sentido dado esse contexto?&lt;/p&gt;

&lt;p&gt;Em muitos momentos, o trabalho era mais pensar do que programar.&lt;/p&gt;




&lt;h2&gt;
  
  
  O que está funcionando hoje
&lt;/h2&gt;

&lt;p&gt;O backend está em produção no Railway. Todas as funcionalidades do core foram validadas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cadastro e autenticação JWT&lt;/li&gt;
&lt;li&gt;Upload e processamento do Registrato&lt;/li&gt;
&lt;li&gt;Extração automática de dívidas&lt;/li&gt;
&lt;li&gt;Geração de insights&lt;/li&gt;
&lt;li&gt;Geração de reclamação via Gemini&lt;/li&gt;
&lt;li&gt;Exportação da reclamação em PDF
O frontend está em fase final de integração, com deploy previsto no Vercel.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  O que vem pela frente
&lt;/h2&gt;

&lt;p&gt;A próxima entrega é a primeira versão pública funcional — com interface web completa, integração com o backend em produção, e o fluxo completo acessível para usuários reais.&lt;/p&gt;

&lt;p&gt;Depois disso, o plano inclui:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Onboarding guiado para novos usuários&lt;/li&gt;
&lt;li&gt;Expansão dos tipos de documentos suportados&lt;/li&gt;
&lt;li&gt;Refinamento do modelo de geração de reclamações&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Estudar a viabilidade de monetização
&lt;/h2&gt;

&lt;h2&gt;
  
  
  O que esse projeto me ensinou
&lt;/h2&gt;

&lt;p&gt;Projetos fictícios ensinam sintaxe. Projetos reais ensinam a pensar como engenheiro.&lt;/p&gt;

&lt;p&gt;A diferença está na pressão que um problema real cria. Quando você sabe que existe alguém do outro lado que pode ser ajudado, as decisões ganham peso. Você não pula etapas. Você não aceita uma solução que só funciona no caminho feliz.&lt;/p&gt;

&lt;p&gt;E talvez o aprendizado mais honesto dessa jornada seja que IA não substitui engenharia de software. Ela amplifica. Quando você sabe o que quer construir, quando tem clareza sobre o problema, a IA acelera. Quando você não tem, ela só gera confusão mais rápido.&lt;/p&gt;

&lt;p&gt;O Quita ainda não está pronto. Mas está mais próximo do que nunca.&lt;/p&gt;

&lt;p&gt;E foi construído para resolver um problema real, com tecnologia real, para pessoas reais.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>braziliandevs</category>
      <category>java</category>
      <category>specdriven</category>
    </item>
    <item>
      <title>En:Building a RAG Agent for SOPs</title>
      <dc:creator>Cleber Lucas</dc:creator>
      <pubDate>Tue, 09 Jun 2026 16:53:55 +0000</pubDate>
      <link>https://dev.to/obelucca__/enbuilding-a-rag-agent-for-sops-5hj1</link>
      <guid>https://dev.to/obelucca__/enbuilding-a-rag-agent-for-sops-5hj1</guid>
      <description>&lt;h1&gt;
  
  
  How I built a RAG agent to eliminate operational interruptions at work
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Open source project using Python, LangChain, ChromaDB, FastAPI and Discord — from a real problem to production deployment.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Every company has a silent cycle that drains time without anyone noticing.&lt;/p&gt;

&lt;p&gt;An employee has a question about a procedure. They can't find the answer in the documentation. They interrupt a more experienced colleague. That person stops what they're doing, answers, and goes back to work — focus already broken. Multiply that by 10, 20, 50 times a week.&lt;/p&gt;

&lt;p&gt;Watching that pattern is what led me to build &lt;strong&gt;POPS AI&lt;/strong&gt;: a RAG &lt;em&gt;(Retrieval-Augmented Generation)&lt;/em&gt; agent capable of answering questions about a company's Standard Operating Procedures, directly through Discord or via a REST API.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem that motivated the project
&lt;/h2&gt;

&lt;p&gt;The company had dozens of SOPs documented in PDF format. The problem wasn't a lack of documentation — it was the friction in accessing it. Nobody opens a network folder, hunts for the right file, and reads 15 pages just to answer a quick question.&lt;/p&gt;

&lt;p&gt;The question I asked myself was simple: &lt;strong&gt;what if the documentation could answer questions on its own?&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The architecture in three stages
&lt;/h2&gt;

&lt;p&gt;The system works in three distinct phases, each with a clear responsibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Extraction
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;extrair_texto.py&lt;/code&gt; script reads PDFs from the &lt;code&gt;pops_originais/&lt;/code&gt; folder, extracts the full text using PyMuPDF, and saves it as &lt;code&gt;.txt&lt;/code&gt;. Page images are also extracted for future use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fitz&lt;/span&gt;  &lt;span class="c1"&gt;# PyMuPDF
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_text_from_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fitz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;full_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;full_text&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;full_text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, but important: extraction quality determines response quality. Scanned PDFs without OCR are enemy number one here.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Embedding generation
&lt;/h3&gt;

&lt;p&gt;With the extracted texts, &lt;code&gt;gerar_embeddings.py&lt;/code&gt; splits the content into chunks using LangChain's &lt;code&gt;RecursiveCharacterTextSplitter&lt;/code&gt;, generates the vectors, and persists them in ChromaDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;

&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;chunk_overlap=200&lt;/code&gt; was a deliberate choice: it ensures context isn't cut off abruptly between chunks, which visibly improved response coherence.&lt;/p&gt;

&lt;p&gt;The project supports two embedding models via &lt;code&gt;config.py&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemini &lt;code&gt;models/embedding-001&lt;/code&gt;&lt;/strong&gt; — high quality, requires API key, cost scales with volume&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local SBERT (&lt;code&gt;paraphrase-multilingual-mpnet-base-v2&lt;/code&gt;)&lt;/strong&gt; — runs offline, great for avoiding costs or rate limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This flexibility was one of the design decisions that added the most value, especially for anyone who wants to experiment with the project at zero cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Query (RAG)
&lt;/h3&gt;

&lt;p&gt;When a user asks a question, the system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Converts the question into a vector using the same embedding model&lt;/li&gt;
&lt;li&gt;Searches for the most semantically similar chunks in ChromaDB&lt;/li&gt;
&lt;li&gt;Builds a prompt with the retrieved excerpts as context&lt;/li&gt;
&lt;li&gt;Sends it to Gemini 2.0 Flash to generate the final answer
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;query_embeddings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;question_embedding&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;n_results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are an assistant specialized in the company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s SOPs.
Use only the information below to answer.

Context:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Question: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The interfaces: Discord and API
&lt;/h2&gt;

&lt;p&gt;The project exposes the knowledge base in two ways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discord bot&lt;/strong&gt; with slash commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/pop &amp;lt;question&amp;gt;&lt;/code&gt; — queries the vector database and returns the answer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/addpop &amp;lt;file.txt&amp;gt;&lt;/code&gt; — lets admins add new SOPs in real time, without reprocessing the entire base&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;FastAPI REST API&lt;/strong&gt; with a &lt;code&gt;POST /ask&lt;/code&gt; endpoint, designed for integration with other internal systems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"question"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"How do I configure the scanner on the Samsung printer?"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Response&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"answer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"To configure the scanner, follow these steps:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;1. Turn on the printer...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;[Source: SOP-ScannerSetup.txt]"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The challenge nobody talks about: token costs
&lt;/h2&gt;

&lt;p&gt;Building the RAG was the fun part. The real challenge came after: how do you control costs in production?&lt;/p&gt;

&lt;p&gt;A few decisions that made a real difference:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using SBERT for embeddings instead of the Gemini API&lt;/strong&gt; brings indexing cost down to zero — the model runs locally. Cost only occurs at response generation, which is where the actual value is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limiting &lt;code&gt;n_results=5&lt;/code&gt; in the vector search&lt;/strong&gt; avoids passing unnecessary context to the model. More context = more tokens = more cost, without necessarily improving the answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini 2.0 Flash&lt;/strong&gt; was chosen intentionally over Pro: for objective questions about procedures, the quality difference is minimal while the cost difference is significant.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deployment: one container, two processes
&lt;/h2&gt;

&lt;p&gt;One decision that cost me a few hours was running the Discord bot and the FastAPI server in the same Docker container. The solution was &lt;strong&gt;Supervisor&lt;/strong&gt;, which manages both processes in a lightweight, self-recovering way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# supervisord.conf
&lt;/span&gt;&lt;span class="nn"&gt;[program:api]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;uvicorn api_bot:app --host 0.0.0.0 --port 8000&lt;/span&gt;

&lt;span class="nn"&gt;[program:discord]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;python bot_discord.py&lt;/span&gt;

&lt;span class="py"&gt;autostart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;autorestart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a single, lightweight container that starts both services in parallel and automatically restarts either one if it fails. On an entry-level VPS, this matters a lot.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned that wasn't in the plan
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Chunking is an art.&lt;/strong&gt; Chunk size and overlap affect response quality more than the model itself. I spent more time tuning this than anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security from day one.&lt;/strong&gt; The &lt;code&gt;.gitignore&lt;/code&gt; had to be configured before the first public commit to ensure no confidential company PDFs ended up in the repository. A mistake here is hard to undo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real problem wasn't technical.&lt;/strong&gt; The most complex part was understanding what kind of questions users would actually ask and how to structure the SOPs so the model could retrieve the right information. Garbage in, garbage out applies twice as hard in RAG.&lt;/p&gt;




&lt;h2&gt;
  
  
  The project is open source
&lt;/h2&gt;

&lt;p&gt;POPS AI is available on GitHub with a full README, &lt;code&gt;.env.example&lt;/code&gt;, configured Docker Compose, and step-by-step setup instructions for both local and container-based deployment.&lt;/p&gt;

&lt;p&gt;You can clone it, adapt it to your own knowledge base, and use it with your own documents — whether for SOPs, internal wikis, product manuals, or any PDF-based documentation.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/obelucca/POPS_AI" rel="noopener noreferrer"&gt;github.com/obelucca/POPS_AI&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Python 3.10&lt;/code&gt; &lt;code&gt;LangChain&lt;/code&gt; &lt;code&gt;ChromaDB&lt;/code&gt; &lt;code&gt;FastAPI&lt;/code&gt; &lt;code&gt;Discord.py&lt;/code&gt; &lt;code&gt;Google Gemini 2.0 Flash&lt;/code&gt; &lt;code&gt;SBERT&lt;/code&gt; &lt;code&gt;Docker&lt;/code&gt; &lt;code&gt;Supervisor&lt;/code&gt; &lt;code&gt;PyMuPDF&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you made it this far and are curious about any architectural decision, token cost management in production, or how to adapt this to a different use case — drop a comment. Happy to discuss.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>rag</category>
      <category>langchain</category>
    </item>
    <item>
      <title>Do PDF ao Discord com RAG: Como construí um agente RAG para eliminar interrupções operacionais na empresa</title>
      <dc:creator>Cleber Lucas</dc:creator>
      <pubDate>Tue, 09 Jun 2026 13:51:49 +0000</pubDate>
      <link>https://dev.to/obelucca__/do-pdf-ao-discord-com-rag-como-construi-um-agente-rag-para-eliminar-interrupcoes-operacionais-na-48n5</link>
      <guid>https://dev.to/obelucca__/do-pdf-ao-discord-com-rag-como-construi-um-agente-rag-para-eliminar-interrupcoes-operacionais-na-48n5</guid>
      <description>&lt;h1&gt;
  
  
  Como construí um agente RAG para eliminar interrupções operacionais na empresa
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Projeto open source com Python, LangChain, ChromaDB, FastAPI e Discord — do problema real ao deploy em produção.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Toda empresa tem aquele ciclo silencioso que drena tempo sem que ninguém perceba.&lt;/p&gt;

&lt;p&gt;Um funcionário tem uma dúvida sobre um procedimento. Não encontra a resposta nos documentos. Interrompe alguém mais experiente. Essa pessoa para o que estava fazendo, responde, e volta ao trabalho — já com o raciocínio quebrado. Multiplique isso por 10, 20, 50 vezes por semana.&lt;/p&gt;

&lt;p&gt;Foi observando esse padrão que decidi construir o &lt;strong&gt;POPS AI&lt;/strong&gt;: um agente de RAG &lt;em&gt;(Retrieval-Augmented Generation)&lt;/em&gt; capaz de responder perguntas sobre os Procedimentos Operacionais Padrão de uma empresa, direto pelo Discord ou via API REST.&lt;/p&gt;




&lt;h2&gt;
  
  
  O problema que motivou o projeto
&lt;/h2&gt;

&lt;p&gt;A empresa tinha dezenas de POPs documentados em PDF. O problema não era a falta de documentação — era o atrito para acessá-la. Ninguém abre uma pasta de rede, procura o arquivo certo e lê 15 páginas para responder uma dúvida pontual.&lt;/p&gt;

&lt;p&gt;A pergunta que me fiz foi simples: &lt;strong&gt;e se a documentação pudesse responder sozinha?&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A arquitetura em três etapas
&lt;/h2&gt;

&lt;p&gt;O sistema funciona em três fases distintas, cada uma com responsabilidade clara.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Extração
&lt;/h3&gt;

&lt;p&gt;O script &lt;code&gt;extrair_texto.py&lt;/code&gt; lê os PDFs da pasta &lt;code&gt;pops_originais/&lt;/code&gt;, extrai o texto completo com PyMuPDF e salva em &lt;code&gt;.txt&lt;/code&gt;. Imagens das páginas também são extraídas para uso futuro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fitz&lt;/span&gt;  &lt;span class="c1"&gt;# PyMuPDF
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extrair_texto_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caminho_pdf&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fitz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caminho_pdf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;texto_completo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pagina&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;texto_completo&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;pagina&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;texto_completo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simples, mas importante: a qualidade da extração determina a qualidade das respostas. PDFs escaneados sem OCR são o inimigo número um aqui.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Geração de embeddings
&lt;/h3&gt;

&lt;p&gt;Com os textos extraídos, o &lt;code&gt;gerar_embeddings.py&lt;/code&gt; divide o conteúdo em chunks usando o &lt;code&gt;RecursiveCharacterTextSplitter&lt;/code&gt; da LangChain, gera os vetores e persiste no ChromaDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;

&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;chunk_overlap=200&lt;/code&gt; foi uma decisão deliberada: ele garante que o contexto não seja cortado abruptamente entre um chunk e o próximo, o que melhorou visivelmente a coerência das respostas.&lt;/p&gt;

&lt;p&gt;O projeto suporta dois modelos de embedding via &lt;code&gt;config.py&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemini &lt;code&gt;models/embedding-001&lt;/code&gt;&lt;/strong&gt; — qualidade alta, requer API key e gera custo por volume&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SBERT local (&lt;code&gt;paraphrase-multilingual-mpnet-base-v2&lt;/code&gt;)&lt;/strong&gt; — roda offline, ótimo para evitar custos ou limites de requisição&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essa flexibilidade foi uma das decisões de design que mais agregou valor, especialmente para quem quer experimentar o projeto sem gastar nada.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Consulta (RAG)
&lt;/h3&gt;

&lt;p&gt;Quando o usuário faz uma pergunta, o sistema:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Converte a pergunta em vetor usando o mesmo modelo de embedding&lt;/li&gt;
&lt;li&gt;Busca os chunks mais semanticamente similares no ChromaDB&lt;/li&gt;
&lt;li&gt;Monta um prompt com os trechos recuperados como contexto&lt;/li&gt;
&lt;li&gt;Envia para o Gemini 2.0 Flash gerar a resposta final
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;resultados&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;query_embeddings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;embedding_pergunta&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;n_results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;contexto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultados&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Você é um assistente especializado nos POPs da empresa.
Use apenas as informações abaixo para responder.

Contexto:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Pergunta: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pergunta&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  As interfaces: Discord e API
&lt;/h2&gt;

&lt;p&gt;O projeto expõe a base de conhecimento de duas formas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bot do Discord&lt;/strong&gt; com slash commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/pop &amp;lt;pergunta&amp;gt;&lt;/code&gt; — consulta a base vetorial e retorna a resposta&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/addpop &amp;lt;arquivo.txt&amp;gt;&lt;/code&gt; — permite que administradores adicionem novos POPs em tempo real, sem precisar reprocessar toda a base&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;API FastAPI&lt;/strong&gt; com endpoint &lt;code&gt;POST /ask&lt;/code&gt;, pensada para integrar com outros sistemas internos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"question"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Como configurar o scanner da impressora Samsung?"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Response&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"answer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Para configurar o scanner, siga os passos:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;1. Ligue a impressora...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;[Fonte: POP-ConfiguraçãoScanner.txt]"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  O desafio que ninguém menciona: custo de tokens
&lt;/h2&gt;

&lt;p&gt;Construir o RAG foi a parte divertida. O desafio real veio depois: como controlar o custo em produção?&lt;/p&gt;

&lt;p&gt;Algumas decisões que fizeram diferença:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usar SBERT para embeddings em vez da API do Gemini&lt;/strong&gt; reduz o custo de indexação para zero — o modelo roda localmente. O custo só existe na geração de resposta, que é onde o valor real está.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitar &lt;code&gt;n_results=5&lt;/code&gt; na busca vetorial&lt;/strong&gt; evita passar contexto desnecessário para o modelo. Mais contexto = mais tokens = mais custo, sem necessariamente melhorar a resposta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini 2.0 Flash&lt;/strong&gt; foi escolhido intencionalmente sobre o Pro: para perguntas objetivas sobre procedimentos, a diferença de qualidade é mínima e a diferença de custo é expressiva.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deploy: um container, dois processos
&lt;/h2&gt;

&lt;p&gt;Uma decisão que me custou algumas horas foi rodar o bot do Discord e a API FastAPI no mesmo container Docker. A solução foi o &lt;strong&gt;Supervisor&lt;/strong&gt;, que gerencia ambos os processos de forma leve e auto-recuperável.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# supervisord.conf
&lt;/span&gt;&lt;span class="nn"&gt;[program:api]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;uvicorn api_bot:app --host 0.0.0.0 --port 8000&lt;/span&gt;

&lt;span class="nn"&gt;[program:discord]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;python bot_discord.py&lt;/span&gt;

&lt;span class="py"&gt;autostart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;autorestart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado é um container único, leve, que sobe os dois serviços em paralelo e reinicia automaticamente qualquer um que falhe. Para uma VPS de entrada, isso faz toda a diferença.&lt;/p&gt;




&lt;h2&gt;
  
  
  O que aprendi que não estava no plano
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Chunking é uma arte.&lt;/strong&gt; O tamanho e o overlap dos chunks afetam mais a qualidade das respostas do que o modelo em si. Passei mais tempo ajustando isso do que qualquer outra coisa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Segurança desde o início.&lt;/strong&gt; O &lt;code&gt;.gitignore&lt;/code&gt; precisou ser configurado antes do primeiro commit público para garantir que nenhum PDF com dados confidenciais da empresa fosse parar no repositório. Um erro aqui é difícil de reverter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O problema real não era técnico.&lt;/strong&gt; A parte mais complexa foi entender que tipo de pergunta os usuários fariam e como estruturar os POPs para que o modelo conseguisse recuperar as informações certas. Garbage in, garbage out vale dobrado em RAG.&lt;/p&gt;




&lt;h2&gt;
  
  
  O projeto é open source
&lt;/h2&gt;

&lt;p&gt;O POPS AI está disponível no GitHub com README completo, &lt;code&gt;.env.example&lt;/code&gt;, Docker Compose configurado e passo a passo de instalação tanto local quanto via container.&lt;/p&gt;

&lt;p&gt;Você pode clonar, adaptar para sua própria base de conhecimento e usar com seus próprios documentos — seja para POPs, wikis internas, manuais de produto ou qualquer documentação em PDF.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/obelucca/POPS_AI" rel="noopener noreferrer"&gt;github.com/obelucca/POPS_AI&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack utilizada
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Python 3.10&lt;/code&gt; &lt;code&gt;LangChain&lt;/code&gt; &lt;code&gt;ChromaDB&lt;/code&gt; &lt;code&gt;FastAPI&lt;/code&gt; &lt;code&gt;Discord.py&lt;/code&gt; &lt;code&gt;Google Gemini 2.0 Flash&lt;/code&gt; &lt;code&gt;SBERT&lt;/code&gt; &lt;code&gt;Docker&lt;/code&gt; &lt;code&gt;Supervisor&lt;/code&gt; &lt;code&gt;PyMuPDF&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Se você chegou até aqui e tem curiosidade sobre alguma decisão de arquitetura, custo de tokens em produção ou como adaptar para um caso de uso diferente — deixa nos comentários. Bora trocar ideia.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>rag</category>
      <category>langchain</category>
    </item>
  </channel>
</rss>
