Olá a todos!
Perguntam-me frequentemente: “Nuno, porque é que insistes em soluções self-hosted quando temos o GitHub Copilot, ChatGPT e outros assistentes de programação na nuvem tão avançados?”
A resposta é simples: alucinações. E não, não estou a falar de algo que se resolve com mais café ou uma boa noite de sono.
Vi recentemente desenho de arquiteturas self hosted para combater o problema e trago-vos uma que depois de experimentar me pareceu bastante boa.
O Problema Real das Alucinações em Código
Vamos ser brutalmente honestos: as alucinações em IA são o elefante na sala que todos fingimos não ver. É impossível preveni-las completamente – são literalmente um bug, não uma feature, do funcionamento dos modelos de linguagem modernos. E quando estamos a falar de código? Vibe coding ftw?!
O Código que Mente (E Mente Bem)
Já passaram por aquela situação em que o Copilot vos sugere uma função que parece saída diretamente do manual da API? Perfeita, elegante, exatamente o que precisavam? E depois passam duas horas a descobrir que essa função nunca existiu na vida real? Bem-vindos ao clube.
O problema das alucinações em programação não é só irritante – é perigoso. Estamos a falar de:
Funções fantasma: APIs que parecem reais mas são pura ficção científica. O modelo viu padrões, extrapolou, e criou uma realidade paralela onde essa função existe.
Lógica traiçoeira: Código que compila na boa, passa nos testes básicos, mas depois falha espetacularmente em produção. É como ter um carro que arranca bem no stand, mas as rodas caem quando entram na autoestrada.
Padrões do Jurássico: Sugestões baseadas em versões de bibliotecas que já têm barbas. Resultado? Código que introduz vulnerabilidades que já foram resolvidas há anos.
O cavalo de Tróia digital: O mais insidioso de todos – código que parece inocente mas introduz falhas de segurança que só são descobertas quando já é tarde demais.
O Verdadeiro Problema
O pior de tudo isto? Este código parece correto. Não é como aqueles erros óbvios que qualquer júnior apanha. Não, este código tem boa pinta, segue convenções, até pode ter comentários explicativos. É o crime perfeito do mundo digital.
E aqui surge a pergunta que não quer calar: quantos de nós já fizeram “vibe coding” com base numa sugestão de IA? Aquela programação por intuição, onde confiamos que a máquina sabe o que está a fazer porque, honestamente, também nós não sabemos bem?
A Realidade Nua e Crua
As alucinações não vão desaparecer. Fazem parte do ADN destes modelos. São o preço que pagamos por ter assistentes de código que conseguem entender contexto e gerar soluções criativas.
Mas isso não significa que devemos aceitar passivamente. Significa que temos de ser mais espertos, mais céticos, mais… humanos no nosso approach à programação assistida por IA.
Porque no final do dia, o código pode mentir, mas a realidade não perdoa.
Então Porque é que Self-Hosted é a Resposta?
Quais os pré requisitos fundamentais para ter o controle sobre a alucinação? O que podemos fazer?
1. Controlo Total dos Dados
Primeira razão óbvia: o nosso código proprietário nunca sai da nossa infraestrutura. Zero. Nada. Com as recentes decisões judiciais sobre preservação de dados, isto não é paranóia – é necessidade.
Seja com uma KB conforme falamos no post anterior sobre MCP, seja com documentação interna a nossa empresa ou startup.
2. Fine-Tuning com o Nosso Context
Aqui é onde a coisa fica interessante. Podem treinar o modelo com:
- Codebase interno – os nossos padrões e convenções específicas
- Bibliotecas proprietárias – APIs e frameworks que desenvolvemos internamente
- Histórico de bugs – padrões que já causaram problemas antes
- Standards organizacionais – as nossas melhores práticas
3. Validação em Tempo Real
A magia acontece quando integram o sistema com o vosso ambiente de desenvolvimento:
class CodeValidator:
def __init__(self, project_context):
self.project_context = project_context
self.syntax_checker = SyntaxChecker()
self.semantic_analyzer = SemanticAnalyzer()
def validate_suggestion(self, code_suggestion):
# Verificação sintática
if not self.syntax_checker.is_valid(code_suggestion):
return ValidationResult.SYNTAX_ERROR
# Verificação semântica contra o contexto local
if not self.semantic_analyzer.analyze(code_suggestion, self.project_context):
return ValidationResult.SEMANTIC_ERROR
# Verificação contra bibliotecas instaladas
if not self.check_compatibility(code_suggestion):
return ValidationResult.COMPATIBILITY_ERROR
return ValidationResult.VALID
A Arquitetura Anti-Alucinação
A chave para combater alucinações está numa arquitetura em camadas onde cada nível adiciona uma barreira de proteção. Pensem nisto como um sistema de defesa em profundidade – se uma camada falha, as outras apanham o erro. Assim sendo, temos o seguinte esquema:
Camada 1: O Modelo Local (O Cérebro)
Esta é a base de tudo – o modelo de linguagem que gera as sugestões. A escolha aqui determina 80% do sucesso do sistema.
CodeLlama (7B-34B parâmetros)
- Pontos fortes: Excelente para Python, C++, JavaScript. Fine-tuning relativamente simples
- Recursos: 7B precisa de 8GB VRAM mínimo, 34B precisa de 24GB+
- Uso prático: Ideal para equipas que trabalham principalmente com estas linguagens
- Licença: Permite uso comercial com restrições menores
StarCoder (3B-15B parâmetros)
- Pontos fortes: Suporte para 80+ linguagens, treinado em código open-source de qualidade
- Recursos: Mais eficiente em GPU, 15B funciona bem com 16GB VRAM
- Uso prático: Melhor escolha para equipas polyglot ou com linguagens menos comuns
- Licença: OpenRAIL, permite uso comercial
Tabby (1B-3B parâmetros)
- Pontos fortes: Setup plug-and-play, interface web incluída, consume menos recursos
- Recursos: Funciona até em RTX 3080, 3B modelo precisa apenas 6GB VRAM
- Uso prático: Perfeito para começar ou equipas pequenas
- Licença: Apache 2.0, totalmente livre
Qwen-Coder (30B parâmetros)
- Pontos fortes: Extremamente afinado para o pretendido. Excelente em código complexo, com contextos longos.
- Recursos: Funciona até em duas RTX 4060ti com 16GB de VRAM, modelo precisa de 30GB VRAM dependendo do tamanho do contexto.
- Uso prático: Perfeito para equipas avançadas
- Licença: Apache 2.0, totalmente livre
A escolha prática: Para a maioria das equipas, recomendo começar com Tabby 3B. Se tiverem uma RTX 4090 ou superior, experimentem o CodeLlama 13B.
Camada 2: Validação Contextual (O Conhecimento Local)
Esta camada é onde a magia começa a acontecer – é aqui que o sistema “aprende” sobre o vosso projeto específico e pode detetar quando o modelo está a alucinar baseado no vosso contexto real.
Parser de Documentação Local
class DocumentationParser:
def __init__(self, project_root):
self.project_root = project_root
self.api_registry = {}
self.type_definitions = {}
def parse_local_apis(self):
# Scanning de todos os ficheiros Python/JS/etc
for file_path in self.scan_source_files():
# Extrai definições de funções, classes, tipos
definitions = self.extract_definitions(file_path)
self.api_registry.update(definitions)
def validate_function_call(self, function_name, context):
if function_name not in self.api_registry:
return ValidationError(f"Function {function_name} doesn't exist in codebase")
return ValidationSuccess()
Integração com Schemas de Base de Dados
O sistema conecta-se às nossas bases de dados (de novo referencia ao posts anteriores) e mantém um registo atualizado de:
- Tabelas e colunas existentes – evita sugestões de campos que não existem
- Relacionamentos entre tabelas – sugere JOINs corretos baseados nas foreign keys reais
- Índices disponíveis – otimiza queries sugeridas baseado nos índices existentes
- Tipos de dados – evita erros de casting ou comparações inválidas
Análise de Contratos de API Para microserviços e APIs externas:
- OpenAPI/Swagger specs – valida chamadas contra especificações reais
- GraphQL schemas – verifica queries e mutations possíveis
- gRPC definitions – valida service calls e message types
- Histórico de respostas – aprende padrões reais de dados retornados
Gestão de Dependências em Tempo Real
Finalmente e para manter tudo coerente chegamos a esta parte:
class DependencyTracker:
def __init__(self, package_files):
self.installed_packages = self.parse_requirements(package_files)
self.version_constraints = {}
def validate_import(self, import_statement):
package_name = self.extract_package(import_statement)
if package_name not in self.installed_packages:
return ValidationError(f"Package {package_name} not in requirements.txt")
# Verifica se a versão instalada suporta a funcionalidade
if not self.check_version_compatibility(package_name, import_statement):
return ValidationError(f"Function not available in installed version")
return ValidationSuccess()
Camada 3: Verificação Automática (O Laboratório de Testes)
Esta é a camada mais técnica mas também a mais importante – é aqui que testamos tudo antes de sugerir ao developer.
Compilação e Análise Sintática Antes de qualquer sugestão chegar ao IDE, o sistema:
- Compila o código num ambiente sandboxed
- Verifica sintaxe específica da linguagem
- Analisa imports e dependências
- Deteta erros óbvios como variáveis não definidas
Execução de Testes Unitários O sistema mais avançado vai ainda mais longe:
class SuggestionTester:
def __init__(self, test_runner):
self.test_runner = test_runner
self.sandbox = CodeSandbox()
def test_suggestion(self, code_suggestion, affected_functions):
# Aplica a sugestão num ambiente isolado
modified_code = self.apply_suggestion(code_suggestion)
# Executa testes relacionados
test_results = self.test_runner.run_tests_for(affected_functions)
if test_results.failed_count > 0:
return ValidationError("Suggestion breaks existing tests")
# Executa testes de performance simples
perf_impact = self.measure_performance_impact(modified_code)
if perf_impact.degradation > 0.2: # >20% slower
return ValidationWarning("Suggestion may impact performance")
return ValidationSuccess()
Análise Estática Avançada Usando ferramentas como:
- ESLint/TSLint para JavaScript/TypeScript
- Pylint/Flake8 para Python
- SonarQube para análise multi-linguagem
- Semgrep para deteção de padrões de segurança
- PuppetPDK para análise de codigo puppet
Verificação de Segurança Automática
class SecurityValidator:
def __init__(self):
self.security_rules = [
NoHardcodedSecretsRule(),
NoSQLInjectionRule(),
NoXSSVulnerabilitiesRule(),
NoUnsafeDeserializationRule()
]
def validate_security(self, code_suggestion):
violations = []
for rule in self.security_rules:
if rule.violates(code_suggestion):
violations.append(rule.get_violation_message())
if violations:
return SecurityViolation(violations)
return SecurityClearance()
Camada 4: Feedback Loop (A Aprendizagem Contínua)
Esta camada é essencial – o sistema tem de aprender com os erros.
Coleta de Métricas de Utilização
- Que sugestões são aceites vs rejeitadas
- Quanto tempo developers demoram a modificar sugestões
- Que tipos de erro são mais comuns
- Padrões de utilização por equipa/projeto
Refinamento Automático do Modelo Com base no feedback:
- Re-ranking de sugestões baseado em aceitação histórica
- Fine-tuning periódico com exemplos específicos da organização
- Ajuste de confidence thresholds para diferentes tipos de código
- Personalização por developer (alguns preferem sugestões mais conservadoras)
Sistema de Alertas Inteligente
class FeedbackCollector:
def record_suggestion_outcome(self, suggestion_id, outcome, developer_id):
# Regista se foi aceite, modificada, ou rejeitada
self.metrics_db.insert({
'suggestion_id': suggestion_id,
'outcome': outcome, # ACCEPTED, MODIFIED, REJECTED
'developer_id': developer_id,
'timestamp': datetime.now(),
'context': self.get_code_context(suggestion_id)
})
# Analisa padrões para melhorar sugestões futuras
if outcome == 'REJECTED':
self.analyze_rejection_reason(suggestion_id)
Esta arquitetura em camadas garante que mesmo quando o modelo base alucina, o sistema tem múltiplas oportunidades para detetar e corrigir o erro antes de chegar ao developer. É como ter vários pares de olhos a rever cada sugestão – mas de forma automática e em segundos.
Use Cases Onde Isto Brilha
Refactoring de Legacy Code
Tenho visto equipas a usar isto para:
- Identificar padrões obsoletos em codebases antigos
- Sugerir alternativas modernas mantendo compatibilidade
- Validar que as mudanças não quebram funcionalidade existente
Nota: Cuidado com divida técnica, apenas acrescentem ou modifiquem o vosso código legacy se souberem o que estão a escrever. Não assumo responsabilidades por vibe coding irresponsável.
Desenvolvimento de APIs
Para equipas que criam APIs (sim estou a olhar para ti P):
- Validação automática contra especificações OpenAPI
- Sugestões baseadas em contratos existentes
- Verificação de consistência entre documentação e implementação
Microserviços
Em arquiteturas distribuídas:
- Garantir consistência entre serviços
- Validar contratos de comunicação
- Sugerir padrões de resiliência específicos da organização
Os Custos Reais (Que Ninguém Conta)
Chegamos ao elefante na sala. Os custos…. tem custos. Quanto melhor fizermos a nossa torre melhor a teremos de suportar e melhores materiais teremos de utilizar para garantir a sua estabilidade.
Recursos Computacionais
- Hardware especializado – GPUs para inferência eficiente (mínimo RTX 4090 ou equivalente)
- Armazenamento – modelos ocupam entre 7GB a 70GB+
- RAM – pelo menos 32GB para modelos médios
- Largura de banda – para sincronização e atualizações
Conhecimento Especializado
É necessário que alguém na equipa perceba de:
- MLOps – gestão de modelos em produção
- DevOps – automação e monitorização
- Análise de dados – interpretação de métricas de performance
Manutenção Contínua
- Atualizações de modelos (releases trimestrais)
- Patches de segurança
- Evolução da base de conhecimento local
- Monitorização e ajuste fino contínuo
Métricas que Importam
Não basta implementar – as métricas tem de ser medidas, e baseadas nelas, efetuar ajustes.
Qualidade do Código:
- Taxa de sugestões que compilam sem erro
- Percentagem de sugestões aceites pelos developers
- Redução de bugs em comparação com período anterior
Performance do Sistema:
- Tempo de resposta das sugestões (target: <2 segundos)
- Throughput (sugestões por minuto)
- Utilização de recursos (não pode consumir toda a GPU)
Adopção pela Equipa:
- Quantos developers usam regularmente
- Feedback qualitativo sobre utilidade
- Tipos de tarefas onde é mais usado
Alternativas Mais Simples (Para Começar)
Se isto parece demasiado complexo, há opções intermédias:
Tabby – Self-hosted coding assistant com setup mais simples Code Server – VS Code no browser com extensões de IA local Continue.dev – Plugin que funciona com modelos locais LocalAI – API compatível com OpenAI mas executado localmente.
A Realidade: Vale a Pena?
Vou ser brutalmente honesto: não é para toda a gente.
Vale a pena se:
- Trabalham com código altamente sensível
- Têm requisitos rigorosos de compliance
- A equipa tem 10+ developers
- Já têm infraestrutura GPU disponível
- Há budget para conhecimento especializado
- Tem gosto pela coisa
Não vale a pena se:
- São uma startup pequena com recursos limitados
- O código não é particularmente sensível
- Não têm capacidade para MLOps interno
- Preferem focar recursos no produto core
Começar com Uma Implementação Piloto
A minha recomendação: começem pequeno.
- Escolham um projeto interno não-crítico
- Instalem o Tabby numa máquina com GPU decente
- Integrem com um IDE (VS Code é o mais fácil)
- Meçam tudo durante 2-3 meses
- Avaliem os resultados antes de escalar
O Futuro (Que Já Está Aqui)
Os modelos estão a ficar mais eficientes:
- Quantização reduz o tamanho sem perder qualidade
- Modelos especializados para domínios específicos
- Integração mais profunda com ferramentas de desenvolvimento
Mas a tendência é clara: quem controla os dados, controla a qualidade.
Conclusão: Controlo vs Conveniência
As soluções cloud são convenientes, mas vêm com riscos ocultos que muitas equipas só descobrem tarde demais. As soluções self-hosted requerem mais trabalho inicial, mas oferecem:
- Privacidade garantida dos nossos dados
- Controlo total sobre a qualidade das sugestões
- Customização para o nosso contexto específico
- Custos previsíveis a longo prazo
A pergunta não é se as alucinações vão acontecer – é se vão estar preparados quando acontecerem. Para equipas que levam a sério a qualidade do código e a segurança dos dados, self-hosted não é luxo – é necessidade.
Se precisarem de ajuda na implementação, há empresas especializadas que nos podem orientar neste processo.
Até ao próximo post da semana, quase quase de férias e com esperança que não alucinar até lá. E o resto já sabem: Se houver alguma coisa que discordem, ou se virem algo menos correcto já sabem onde me encontrar.
Abraço!
Nuno