feat: Enhance architecture proposal and SQL optimization tools with detailed explanations and new metadata structure
This commit is contained in:
parent
f1b8bfe4b0
commit
7e9149ca72
6 changed files with 111 additions and 27 deletions
|
|
@ -2,21 +2,23 @@
|
||||||
|
|
||||||
## 1) Resumo executivo
|
## 1) Resumo executivo
|
||||||
|
|
||||||
Esta proposta apresenta uma arquitetura moderna baseada em Agno para construção de agentes especializados em performance e refatoração de queries SQL Server e Oracle, com governança, observabilidade e segurança de dados. O objetivo é acelerar a melhoria de desempenho, reduzir custos operacionais e habilitar automações confiáveis em múltiplos setores.
|
Esta proposta apresenta uma arquitetura moderna baseada em Agno para construção de agentes especializados em performance e refatoração de queries SQL Server e Oracle, com governança, observabilidade e segurança de dados. O objetivo é acelerar a melhoria de desempenho, reduzir custos operacionais e habilitar automações confiáveis em múltiplos setores. O desenho prioriza previsibilidade de custos, rastreabilidade e integração com processos corporativos já existentes.
|
||||||
|
|
||||||
## 2) Objetivo do projeto
|
## 2) Objetivo do projeto
|
||||||
|
|
||||||
- Criar um time de agentes especializados em SQL (explicação, otimização, revisão de qualidade e análise conservadora).
|
- Criar um time de agentes especializados em SQL (explicação, otimização, revisão de qualidade e análise conservadora).
|
||||||
- Reaproveitar e evoluir a base existente de prompts e conhecimento.
|
- Reaproveitar e evoluir a base existente de prompts e conhecimento técnico.
|
||||||
- Garantir segurança, rastreabilidade e controle de custo/latência.
|
- Garantir segurança, rastreabilidade e controle de custo/latência desde o MVP.
|
||||||
- Viabilizar RAG corporativo para respostas alinhadas ao conhecimento interno.
|
- Viabilizar RAG corporativo para respostas alinhadas ao conhecimento interno.
|
||||||
|
- Preparar integração com canais corporativos (ex.: Microsoft Teams) para entrada de solicitações.
|
||||||
|
|
||||||
## 3) Escopo funcional
|
## 3) Escopo funcional
|
||||||
|
|
||||||
- Otimização de queries SQL para Oracle e SQL Server.
|
- Otimização de queries SQL para Oracle e SQL Server.
|
||||||
- Revisão por agente de qualidade com diff e riscos.
|
- Revisão por agente de qualidade com diff e análise de risco.
|
||||||
- Análise conservadora para cenários sensíveis.
|
- Análise conservadora para cenários sensíveis e críticos.
|
||||||
- Execução assistida (manual ou semi-automática) com trilha de auditoria.
|
- Execução assistida (manual ou semi-automática) com trilha de auditoria.
|
||||||
|
- Produção de relatórios executivos e técnicos por área/solicitante.
|
||||||
|
|
||||||
## 4) Benefícios para a diretoria
|
## 4) Benefícios para a diretoria
|
||||||
|
|
||||||
|
|
@ -31,8 +33,9 @@ Detalhamento das vantagens:
|
||||||
- **ROI acelerado**: melhora contínua de performance reduz custos de infraestrutura e tempo de execução de cargas críticas.
|
- **ROI acelerado**: melhora contínua de performance reduz custos de infraestrutura e tempo de execução de cargas críticas.
|
||||||
- **Padronização técnica**: boas práticas de SQL e refatoração aplicadas de forma consistente em toda a empresa.
|
- **Padronização técnica**: boas práticas de SQL e refatoração aplicadas de forma consistente em toda a empresa.
|
||||||
- **Velocidade de entrega**: automação de análise e revisão reduz ciclos de aprovação e retrabalho.
|
- **Velocidade de entrega**: automação de análise e revisão reduz ciclos de aprovação e retrabalho.
|
||||||
- **Observabilidade e previsibilidade**: visibilidade clara de custos, latência e impacto das mudanças.
|
- **Observabilidade e previsibilidade**: visibilidade clara de custos, latência e impacto das mudanças por área.
|
||||||
- **Escala por demanda**: agentes podem ser acionados sob demanda por diferentes áreas sem aumentar headcount.
|
- **Escala por demanda**: agentes acionados sob demanda, com priorização por SLA e criticidade.
|
||||||
|
- **Qualidade contínua**: revisão e validação reduzem regressões em ambientes críticos.
|
||||||
|
|
||||||
## 5) Novas possibilidades de automação
|
## 5) Novas possibilidades de automação
|
||||||
|
|
||||||
|
|
@ -41,6 +44,7 @@ Detalhamento das vantagens:
|
||||||
- **Apoio ao refactoring** em migrações e reengenharias.
|
- **Apoio ao refactoring** em migrações e reengenharias.
|
||||||
- **Assistente de engenharia** para padrões corporativos de SQL.
|
- **Assistente de engenharia** para padrões corporativos de SQL.
|
||||||
- **RAG corporativo** para políticas internas, padrões de modelagem e convenções.
|
- **RAG corporativo** para políticas internas, padrões de modelagem e convenções.
|
||||||
|
- **Apoio a squads** com respostas contextualizadas e justificativas técnicas.
|
||||||
|
|
||||||
## 5.1) Cenários de automação por setor
|
## 5.1) Cenários de automação por setor
|
||||||
|
|
||||||
|
|
@ -49,36 +53,42 @@ Detalhamento das vantagens:
|
||||||
- Otimização de relatórios de fechamento e conciliações.
|
- Otimização de relatórios de fechamento e conciliações.
|
||||||
- Revisão automática de queries críticas de faturamento.
|
- Revisão automática de queries críticas de faturamento.
|
||||||
- Alertas de performance para consultas que impactam SLA.
|
- Alertas de performance para consultas que impactam SLA.
|
||||||
|
- Padronização de consultas de provisão e contabilização.
|
||||||
|
|
||||||
### Seguros
|
### Seguros
|
||||||
|
|
||||||
- Refatoração de consultas de sinistros e risco.
|
- Refatoração de consultas de sinistros e risco.
|
||||||
- Otimização de relatórios regulatórios.
|
- Otimização de relatórios regulatórios.
|
||||||
- Padronização de queries de precificação e provisões.
|
- Padronização de queries de precificação e provisões.
|
||||||
|
- Apoio a auditorias internas com relatórios técnicos.
|
||||||
|
|
||||||
### Operações
|
### Operações
|
||||||
|
|
||||||
- Otimização de consultas de processamento em lote.
|
- Otimização de consultas de processamento em lote.
|
||||||
- Identificação de gargalos em pipelines operacionais.
|
- Identificação de gargalos em pipelines operacionais.
|
||||||
- Sugestões de índices e melhorias de execução.
|
- Sugestões de índices e melhorias de execução.
|
||||||
|
- Monitoramento de consultas que degradam serviços críticos.
|
||||||
|
|
||||||
### BI e Analytics
|
### BI e Analytics
|
||||||
|
|
||||||
- Ajustes de queries para dashboards e cubos.
|
- Ajustes de queries para dashboards e cubos.
|
||||||
- Redução de latência em relatórios executivos.
|
- Redução de latência em relatórios executivos.
|
||||||
- Padronização de joins e filtros complexos.
|
- Padronização de joins e filtros complexos.
|
||||||
|
- Análise de custo por relatório e priorização de refatoração.
|
||||||
|
|
||||||
### TI e Engenharia
|
### TI e Engenharia
|
||||||
|
|
||||||
- Revisão e refatoração de SQL em pipelines e integrações.
|
- Revisão e refatoração de SQL em pipelines e integrações.
|
||||||
- Aceleração de migrações entre ambientes e bancos.
|
- Aceleração de migrações entre ambientes e bancos.
|
||||||
- Automação de documentação de queries críticas.
|
- Automação de documentação de queries críticas.
|
||||||
|
- Padronização de pipelines com base em boas práticas corporativas.
|
||||||
|
|
||||||
### Jurídico e Compliance
|
### Jurídico e Compliance
|
||||||
|
|
||||||
- Auditoria automática de queries sensíveis.
|
- Auditoria automática de queries sensíveis.
|
||||||
- Verificação de padrões de acesso e mascaramento.
|
- Verificação de padrões de acesso e mascaramento.
|
||||||
- Geração de relatórios para conformidade interna.
|
- Geração de relatórios para conformidade interna.
|
||||||
|
- Rastreabilidade de alterações com justificativas técnicas.
|
||||||
|
|
||||||
## 6) Arquitetura proposta (Agno-first)
|
## 6) Arquitetura proposta (Agno-first)
|
||||||
|
|
||||||
|
|
@ -86,14 +96,16 @@ Detalhamento das vantagens:
|
||||||
- **Core de negócio exposto como ferramentas**: casos de uso (ex: otimizar, explicar, comparar) invocados via tools.
|
- **Core de negócio exposto como ferramentas**: casos de uso (ex: otimizar, explicar, comparar) invocados via tools.
|
||||||
- **Módulos únicos sob sql_optimizer_team**: todos os componentes centralizados no mesmo namespace.
|
- **Módulos únicos sob sql_optimizer_team**: todos os componentes centralizados no mesmo namespace.
|
||||||
- **Integrações corporativas**: bancos, repositórios de conhecimento, logs e custos.
|
- **Integrações corporativas**: bancos, repositórios de conhecimento, logs e custos.
|
||||||
|
- **Camada de governança**: políticas de acesso, limites de uso e auditoria.
|
||||||
|
|
||||||
## 6.1) Integração com Microsoft Teams
|
## 6.1) Integração com Microsoft Teams
|
||||||
|
|
||||||
- **Canal dedicado**: solicitações feitas diretamente no Teams.
|
- **Canal dedicado**: solicitações feitas diretamente no Teams por usuários autorizados.
|
||||||
- **Comandos orientados**: prompts guiados (ex: “Otimizar query X para Oracle”).
|
- **Comandos orientados**: prompts guiados (ex: “Otimizar query X para Oracle”).
|
||||||
- **Workflows com aprovação**: etapa de validação antes de aplicar mudanças.
|
- **Workflows com aprovação**: etapa de validação antes de aplicar mudanças em produção.
|
||||||
- **Notificações automáticas**: alertas de performance e relatórios em tempo real.
|
- **Notificações automáticas**: alertas de performance e relatórios em tempo real.
|
||||||
- **Trilha de auditoria**: registro de solicitações e respostas por usuário/time.
|
- **Trilha de auditoria**: registro de solicitações e respostas por usuário/time.
|
||||||
|
- **Rotas por squad**: distribuição automática de tarefas por área responsável.
|
||||||
|
|
||||||
## 7) Observabilidade (obrigatório)
|
## 7) Observabilidade (obrigatório)
|
||||||
|
|
||||||
|
|
@ -109,6 +121,7 @@ Métricas mínimas:
|
||||||
- Custo estimado mensal por time/serviço.
|
- Custo estimado mensal por time/serviço.
|
||||||
- Latência média e p95.
|
- Latência média e p95.
|
||||||
- Taxa de retrabalho/recusa.
|
- Taxa de retrabalho/recusa.
|
||||||
|
- Taxa de aprovação e impacto percebido.
|
||||||
|
|
||||||
## 8) Segurança da informação
|
## 8) Segurança da informação
|
||||||
|
|
||||||
|
|
@ -116,12 +129,14 @@ Métricas mínimas:
|
||||||
- **Bloqueio de Deep Search na web** por padrão; uso somente com autorização.
|
- **Bloqueio de Deep Search na web** por padrão; uso somente com autorização.
|
||||||
- **Mascaramento de dados sensíveis** antes do envio ao LLM.
|
- **Mascaramento de dados sensíveis** antes do envio ao LLM.
|
||||||
- **Políticas de retenção** e segregação de dados por área.
|
- **Políticas de retenção** e segregação de dados por área.
|
||||||
|
- **Auditoria completa** de entradas/saídas para rastreabilidade.
|
||||||
|
|
||||||
## 9) RAG corporativo
|
## 9) RAG corporativo
|
||||||
|
|
||||||
- Base de conhecimento interna versionada.
|
- Base de conhecimento interna versionada.
|
||||||
- Ingestão de documentação técnica, padrões, e decisões arquiteturais.
|
- Ingestão de documentação técnica, padrões e decisões arquiteturais.
|
||||||
- Recuperação com filtros por área e confidencialidade.
|
- Recuperação com filtros por área e confidencialidade.
|
||||||
|
- Curadoria contínua com feedback dos times para melhorar a relevância.
|
||||||
|
|
||||||
## 10) Frameworks considerados
|
## 10) Frameworks considerados
|
||||||
|
|
||||||
|
|
@ -129,40 +144,47 @@ Métricas mínimas:
|
||||||
|
|
||||||
- **Pontos fortes**: orquestração de agentes, memória, tools, execução local, integração rápida.
|
- **Pontos fortes**: orquestração de agentes, memória, tools, execução local, integração rápida.
|
||||||
- **Ideal para**: time de agentes especializados e integração customizada.
|
- **Ideal para**: time de agentes especializados e integração customizada.
|
||||||
|
- **Governança**: fácil acoplamento com módulos de observabilidade e segurança.
|
||||||
|
|
||||||
### B) Langflow
|
### B) Langflow
|
||||||
|
|
||||||
- **Pontos fortes**: low-code visual, facilita protótipos e POCs.
|
- **Pontos fortes**: low-code visual, facilita protótipos e POCs.
|
||||||
- **Ideal para**: validação rápida de fluxos e PoCs de RAG.
|
- **Ideal para**: validação rápida de fluxos e PoCs de RAG.
|
||||||
|
- **Limitações**: menor flexibilidade para integrações profundas corporativas.
|
||||||
|
|
||||||
### C) Dify
|
### C) Dify
|
||||||
|
|
||||||
- **Pontos fortes**: plataforma pronta para apps com RAG, autenticação e gestão.
|
- **Pontos fortes**: plataforma pronta para apps com RAG, autenticação e gestão.
|
||||||
- **Ideal para**: portal de uso corporativo com usuários finais.
|
- **Ideal para**: portal de uso corporativo com usuários finais.
|
||||||
|
- **Limitações**: customizações avançadas podem exigir extensões adicionais.
|
||||||
|
|
||||||
## 11) Recomendações de escolha
|
## 11) Recomendações de escolha
|
||||||
|
|
||||||
- **Agno** para o core e a arquitetura principal.
|
- **Agno** para o core e a arquitetura principal.
|
||||||
- **Langflow** para protótipos e desenho de fluxos.
|
- **Langflow** para protótipos e desenho de fluxos.
|
||||||
- **Dify** para distribuição ampla (se desejarem um portal corporativo pronto).
|
- **Dify** para distribuição ampla (se desejarem um portal corporativo pronto).
|
||||||
|
- **Observabilidade** acoplada desde o início (OpenTelemetry + Langfuse/Phoenix).
|
||||||
|
|
||||||
## 12) Roadmap proposto
|
## 12) Roadmap proposto
|
||||||
|
|
||||||
1. **Fase 1**: validação técnica (agentes + prompts + RAG inicial).
|
1. **Fase 1**: validação técnica (agentes + prompts + RAG inicial).
|
||||||
2. **Fase 2**: observabilidade + segurança + governança.
|
2. **Fase 2**: observabilidade + segurança + governança.
|
||||||
3. **Fase 3**: escala para áreas e processos internos.
|
3. **Fase 3**: escala para áreas e processos internos.
|
||||||
|
4. **Fase 4**: integração com Teams e automações cross-area.
|
||||||
|
|
||||||
## 13) Riscos e mitigação
|
## 13) Riscos e mitigação
|
||||||
|
|
||||||
- **Qualidade do output**: mitigado com revisão automática + validação conservadora.
|
- **Qualidade do output**: mitigado com revisão automática + validação conservadora.
|
||||||
- **Custo**: mitigado com observabilidade e limites de uso.
|
- **Custo**: mitigado com observabilidade e limites de uso por time.
|
||||||
- **Vazamento de dados**: mitigado com RAG isolado e mascaramento.
|
- **Vazamento de dados**: mitigado com RAG isolado e mascaramento.
|
||||||
|
- **Mudanças não controladas**: mitigado com workflow de aprovação.
|
||||||
|
|
||||||
## 14) Próximos passos
|
## 14) Próximos passos
|
||||||
|
|
||||||
- Alinhamento técnico com @Rodrigo Bittencourt De Macedo.
|
- Alinhamento técnico com @Rodrigo Bittencourt De Macedo.
|
||||||
- Definição do escopo mínimo viável (Oracle + SQL Server).
|
- Definição do escopo mínimo viável (Oracle + SQL Server).
|
||||||
- Aprovação do framework prioritário e das ferramentas de observabilidade.
|
- Aprovação do framework prioritário e das ferramentas de observabilidade.
|
||||||
|
- Definição de critérios de sucesso (KPIs técnicos e executivos).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
18
optimization_metadata.json
Normal file
18
optimization_metadata.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"b6e1d99d9d5dd236": {
|
||||||
|
"query_hash": "b6e1d99d9d5dd236",
|
||||||
|
"original_query": "SELECT DISTINCT\n\nc.customer_id,\n\nc.first_name,\n\nc.last_name,\n\nc.email,\n\nCOUNT(o.order_id) as total_orders,\n\nSUM(CASE WHEN o.status = 'completed' THEN 1 ELSE 0 END) as completed_orders,\n\nSUM(CASE WHEN o.status = 'pending' THEN 1 ELSE 0 END) as pending_orders,\n\nAVG(o.total_amount) as avg_order_value,\n\nMAX(o.order_date) as last_order_date,\n\nCASE\n\nWHEN COUNT(o.order_id) > 50 THEN 'VIP'\n\nWHEN COUNT(o.order_id) > 20 THEN 'Premium'\n\nWHEN COUNT(o.order_id) > 5 THEN 'Regular'\n\nELSE 'New'\n\nEND as customer_tier\n\nFROM customers c\n\nLEFT JOIN orders o ON o.customer_id = c.customer_id\n\nWHERE c.customer_id IN (\n\nSELECT DISTINCT o19.customer_id\n\nFROM orders o19\n\nWHERE o19.order_date >= SYSDATE - 730\n\n)\n\nAND c.email LIKE '%@%'\n\nGROUP BY c.customer_id, c.first_name, c.last_name, c.email\n\nHAVING COUNT(o.order_id) > 0\n\nORDER BY COUNT(o.order_id) DESC",
|
||||||
|
"explanation": "1. **Overall Purpose**\nThe query is designed to retrieve a list of customers, their order details, and a classification of their customer tier based on the number of orders they have placed. The query is intended to provide a detailed view of customer activity, including the total number of orders, the number of completed and pending orders, the average order value, the date of the last order, and a classification of the customer based on their order volume.\n\n2. **Involved Database Objects**\nThe query involves two tables: `customers` and `orders`. It also includes a subquery on the `orders` table.\n\n3. **Essential Operations**\n- The query retrieves the following columns: `c.customer_id`, `c.first_name`, `c.last_name`, `c.email`, `total_orders`, `completed_orders`, `pending_orders`, `avg_order_value`, `last_order_date`, and `customer_tier`.\n- A LEFT JOIN is performed between the `customers` table (aliased as `c`) and the `orders` table (aliased as `o`) on the condition that `o.customer_id = c.customer_id`.\n- The WHERE clause filters the customers based on two conditions: the customer's ID must be in the list of customer IDs who have placed an order in the last two years (730 days), and the customer's email must contain an '@' symbol.\n- The COUNT function is used to calculate the total number of orders per customer (`total_orders`), and the SUM function is used with a CASE statement to calculate the number of completed and pending orders.\n- The AVG function is used to calculate the average order value (`avg_order_value`), and the MAX function is used to determine the date of the last order (`last_order_date`).\n- A CASE statement is used to classify customers into tiers based on the number of orders they have placed.\n- The GROUP BY clause groups the results by `c.customer_id`, `c.first_name`, `c.last_name`, and `c.email`.\n- The HAVING clause filters out customers who have not placed any orders.\n- The ORDER BY clause sorts the results in descending order based on the total number of orders.\n\n4. **Performance Issues**\n- The query uses a leading wildcard in the LIKE condition (`c.email LIKE '%@%'`), which can prevent the use of indexes and slow down the query.\n- The subquery in the WHERE clause could potentially be a performance issue, depending on the size of the `orders` table and the number of distinct customer IDs. It might be more efficient to use a JOIN instead.\n- The query uses multiple COUNT functions in the SELECT and ORDER BY clauses, which could be a performance issue if the number of rows is large. It might be more efficient to calculate the count once and store it in a variable or a temporary table.",
|
||||||
|
"database_type": "postgresql",
|
||||||
|
"version": "1.1",
|
||||||
|
"optimized_at": "2026-01-21T17:31:17.127080+00:00"
|
||||||
|
},
|
||||||
|
"60243f154ec1c6c5": {
|
||||||
|
"query_hash": "60243f154ec1c6c5",
|
||||||
|
"original_query": "SELECT DISTINCT\n\nc.customer_id,\n\nc.first_name,\n\nc.last_name,\n\nc.email,\n\n(SELECT COUNT() FROM orders o1 WHERE o1.customer_id = c.customer_id) as total_orders,\n\n(SELECT COUNT() FROM orders o2 WHERE o2.customer_id = c.customer_id AND o2.status = 'completed') as completed_orders,\n\n(SELECT COUNT() FROM orders o3 WHERE o3.customer_id = c.customer_id AND o3.status = 'pending') as pending_orders,\n\n(SELECT AVG(o5.total_amount) FROM orders o5 WHERE o5.customer_id = c.customer_id) as avg_order_value,\n\n(SELECT MAX(o6.order_date) FROM orders o6 WHERE o6.customer_id = c.customer_id) as last_order_date,\n\nCASE\n\nWHEN (SELECT COUNT() FROM orders o8 WHERE o8.customer_id = c.customer_id) > 50 THEN 'VIP'\n\nWHEN (SELECT COUNT() FROM orders o9 WHERE o9.customer_id = c.customer_id) > 20 THEN 'Premium'\n\nWHEN (SELECT COUNT() FROM orders o10 WHERE o10.customer_id = c.customer_id) > 5 THEN 'Regular'\n\nELSE 'New'\n\nEND as customer_tier\n\nFROM customers c\n\nWHERE c.customer_id IN (\n\nSELECT DISTINCT o19.customer_id\n\nFROM orders o19\n\nWHERE o19.order_date >= SYSDATE - 730\n\n)\n\nAND EXISTS (\n\nSELECT 1 FROM orders o21 WHERE o21.customer_id = c.customer_id\n\n)\n\nAND c.email LIKE '%@%'\n\nORDER BY (SELECT COUNT(*) FROM orders o22 WHERE o22.customer_id = c.customer_id) DESC.",
|
||||||
|
"explanation": "1. **Overall Purpose**\nThe query retrieves a list of customers and their order details from an Oracle database. It provides a summary of each customer's order history, including the total number of orders, the number of completed and pending orders, the average order value, the date of the last order, and a customer tier based on the total number of orders. The query is designed to only include customers who have placed an order in the last two years, have at least one order in the system, and have a valid email address.\n\n2. **Involved Database Objects**\nThe query involves two tables: `customers` and `orders`. There are no views, CTEs, stored procedures, temporary tables, or schema-qualified objects involved. The query uses several subqueries and a CASE statement.\n\n3. **Essential Operations**\n- Columns retrieved: `customer_id`, `first_name`, `last_name`, `email` from the `customers` table. The query also calculates and retrieves `total_orders`, `completed_orders`, `pending_orders`, `avg_order_value`, `last_order_date`, and `customer_tier`.\n- There are no joins in this query.\n- Filters and conditions: The query filters customers based on whether they have placed an order in the last two years (`o19.order_date >= SYSDATE - 730`), whether they have at least one order in the system (`EXISTS (SELECT 1 FROM orders o21 WHERE o21.customer_id = c.customer_id)`), and whether they have a valid email address (`c.email LIKE '%@%'`).\n- Aggregations: The query uses `COUNT()` to calculate the total, completed, and pending orders for each customer, `AVG()` to calculate the average order value, and `MAX()` to find the date of the last order.\n- Sorting: The query sorts the results by the total number of orders in descending order (`ORDER BY (SELECT COUNT(*) FROM orders o22 WHERE o22.customer_id = c.customer_id) DESC`).\n- The query uses the `DISTINCT` keyword to ensure that each customer appears only once in the results.\n- Oracle-specific features: The query uses the `SYSDATE` function to get the current date and time.\n\n4. **Performance Issues**\n- The query uses a leading wildcard in the `LIKE` operator (`c.email LIKE '%@%'`). This can prevent the use of an index and slow down the query.\n- The query uses multiple subqueries in the `SELECT` clause, which can be inefficient. These could potentially be replaced with JOINs or window functions for better performance.\n- The query uses a subquery in the `ORDER BY` clause, which can be inefficient. This could potentially be replaced with a calculated column in the main query.\n- The query uses a subquery in the `WHERE` clause to filter customers based on whether they have placed an order in the last two years. This could potentially be replaced with a JOIN for better performance.",
|
||||||
|
"database_type": "oracle",
|
||||||
|
"version": "1.1",
|
||||||
|
"optimized_at": "2026-01-21T17:34:23.063780+00:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,8 +30,8 @@ sql_quality_agent = Agent(
|
||||||
"- Compare a explicação natural com a SQL otimizada e destaque riscos de divergência.",
|
"- Compare a explicação natural com a SQL otimizada e destaque riscos de divergência.",
|
||||||
"- Use checklist: tabelas, colunas, CASE, subqueries, filtros, joins, aliases, cálculos.",
|
"- Use checklist: tabelas, colunas, CASE, subqueries, filtros, joins, aliases, cálculos.",
|
||||||
"- Gere o diff linha a linha usando diff_sql(original_sql, optimized_sql).",
|
"- Gere o diff linha a linha usando diff_sql(original_sql, optimized_sql).",
|
||||||
"- Apresente o diff em formato visual (bloco diff) e depois comente cada alteração em bullets.",
|
"- Apresente o diff em formato visual (lado a lado) e depois comente cada trecho alterado.",
|
||||||
"- Para cada alteração: descreva o que mudou, por que mudou, vantagens, desvantagens e riscos.",
|
"- Para cada trecho alterado: descreva o que mudou, por que mudou, vantagens, desvantagens e riscos.",
|
||||||
"- Se houver risco, solicite correção ao SQL Optimizer com detalhes objetivos.",
|
"- Se houver risco, solicite correção ao SQL Optimizer com detalhes objetivos.",
|
||||||
"- Não reescreva a SQL diretamente.",
|
"- Não reescreva a SQL diretamente.",
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ class AgnoLLMAdapter(BaseLLMAdapter):
|
||||||
"""Adapter that wraps an Agno Model to satisfy the LLMPort interface."""
|
"""Adapter that wraps an Agno Model to satisfy the LLMPort interface."""
|
||||||
|
|
||||||
def __init__(self, model: Model) -> None:
|
def __init__(self, model: Model) -> None:
|
||||||
super().__init__(model.id)
|
|
||||||
self._model = model
|
self._model = model
|
||||||
|
super().__init__(model.id)
|
||||||
|
|
||||||
async def generate_text(
|
async def generate_text(
|
||||||
self, prompt: str, temperature: float = 0.1, max_tokens: int = 4000
|
self, prompt: str, temperature: float = 0.1, max_tokens: int = 4000
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,13 @@ def _work_dir(output_dir: str | None = None) -> Path:
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_db_input(value: str) -> str:
|
||||||
|
cleaned = value.strip().lower()
|
||||||
|
if cleaned in {"sql", "mssql", "ms-sql", "ms_sql"}:
|
||||||
|
return "sqlserver"
|
||||||
|
return cleaned
|
||||||
|
|
||||||
|
|
||||||
def _build_settings(
|
def _build_settings(
|
||||||
database_type: DatabaseType,
|
database_type: DatabaseType,
|
||||||
provider: str | None = None,
|
provider: str | None = None,
|
||||||
|
|
@ -76,7 +83,7 @@ async def explain_query_core(
|
||||||
api_key: str | None = None,
|
api_key: str | None = None,
|
||||||
) -> dict[str, str]:
|
) -> dict[str, str]:
|
||||||
"""Generate a natural-language explanation using the core LLM pipeline."""
|
"""Generate a natural-language explanation using the core LLM pipeline."""
|
||||||
db_type = DatabaseType.from_string(database_type)
|
db_type = DatabaseType.from_string(_normalize_db_input(database_type))
|
||||||
settings = _build_settings(db_type, provider, model, temperature, max_tokens, api_key)
|
settings = _build_settings(db_type, provider, model, temperature, max_tokens, api_key)
|
||||||
llm = LLMAdapterFactory.create(settings)
|
llm = LLMAdapterFactory.create(settings)
|
||||||
generator = PromptGeneratorFactory.create(db_type)
|
generator = PromptGeneratorFactory.create(db_type)
|
||||||
|
|
@ -107,7 +114,7 @@ async def optimize_query_core(
|
||||||
no_review: bool = False,
|
no_review: bool = False,
|
||||||
) -> dict[str, str | dict[str, str]]:
|
) -> dict[str, str | dict[str, str]]:
|
||||||
"""Run the full optimization use case and return the DTO as dict."""
|
"""Run the full optimization use case and return the DTO as dict."""
|
||||||
db_type = DatabaseType.from_string(database_type)
|
db_type = DatabaseType.from_string(_normalize_db_input(database_type))
|
||||||
settings = _build_settings(db_type, provider, model, temperature, max_tokens, api_key)
|
settings = _build_settings(db_type, provider, model, temperature, max_tokens, api_key)
|
||||||
|
|
||||||
llm = LLMAdapterFactory.create(settings)
|
llm = LLMAdapterFactory.create(settings)
|
||||||
|
|
@ -151,7 +158,7 @@ async def compare_optimizations_core(
|
||||||
if not database_types:
|
if not database_types:
|
||||||
raise ValueError("database_types não pode ser vazio")
|
raise ValueError("database_types não pode ser vazio")
|
||||||
|
|
||||||
db_types = [DatabaseType.from_string(db) for db in database_types]
|
db_types = [DatabaseType.from_string(_normalize_db_input(db)) for db in database_types]
|
||||||
settings = _build_settings(db_types[0], provider, model, temperature, max_tokens, api_key)
|
settings = _build_settings(db_types[0], provider, model, temperature, max_tokens, api_key)
|
||||||
|
|
||||||
llm = LLMAdapterFactory.create(settings)
|
llm = LLMAdapterFactory.create(settings)
|
||||||
|
|
|
||||||
|
|
@ -169,23 +169,60 @@ def list_supported_databases(values: Iterable[str]) -> str:
|
||||||
return ", ".join(values)
|
return ", ".join(values)
|
||||||
|
|
||||||
|
|
||||||
|
def _escape_html(text: str) -> str:
|
||||||
|
return (
|
||||||
|
text.replace("&", "&")
|
||||||
|
.replace("<", "<")
|
||||||
|
.replace(">", ">")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def diff_sql(original_sql: str, optimized_sql: str) -> str:
|
def diff_sql(original_sql: str, optimized_sql: str) -> str:
|
||||||
"""Generate a unified diff between original and optimized SQL.
|
"""Generate a side-by-side diff between original and optimized SQL.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
original_sql: Original SQL text
|
original_sql: Original SQL text
|
||||||
optimized_sql: Optimized SQL text
|
optimized_sql: Optimized SQL text
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Unified diff string (line-by-line)
|
Side-by-side diff in HTML table format
|
||||||
"""
|
"""
|
||||||
original_lines = original_sql.strip().splitlines()
|
original_lines = original_sql.strip().splitlines()
|
||||||
optimized_lines = optimized_sql.strip().splitlines()
|
optimized_lines = optimized_sql.strip().splitlines()
|
||||||
diff = difflib.unified_diff(
|
|
||||||
original_lines,
|
matcher = difflib.SequenceMatcher(a=original_lines, b=optimized_lines)
|
||||||
optimized_lines,
|
rows: list[str] = []
|
||||||
fromfile="original.sql",
|
|
||||||
tofile="optimized.sql",
|
for tag, i1, i2, j1, j2 in matcher.get_opcodes():
|
||||||
lineterm="",
|
if tag == "equal":
|
||||||
)
|
for left, right in zip(original_lines[i1:i2], optimized_lines[j1:j2]):
|
||||||
return "\n".join(diff)
|
rows.append(
|
||||||
|
f"<tr><td><pre>{_escape_html(left)}</pre></td><td><pre>{_escape_html(right)}</pre></td></tr>"
|
||||||
|
)
|
||||||
|
elif tag == "replace":
|
||||||
|
left_chunk = original_lines[i1:i2]
|
||||||
|
right_chunk = optimized_lines[j1:j2]
|
||||||
|
max_len = max(len(left_chunk), len(right_chunk))
|
||||||
|
for idx in range(max_len):
|
||||||
|
left = left_chunk[idx] if idx < len(left_chunk) else ""
|
||||||
|
right = right_chunk[idx] if idx < len(right_chunk) else ""
|
||||||
|
rows.append(
|
||||||
|
f"<tr><td><pre>{_escape_html(left)}</pre></td><td><pre>{_escape_html(right)}</pre></td></tr>"
|
||||||
|
)
|
||||||
|
elif tag == "delete":
|
||||||
|
for left in original_lines[i1:i2]:
|
||||||
|
rows.append(
|
||||||
|
f"<tr><td><pre>{_escape_html(left)}</pre></td><td><pre></pre></td></tr>"
|
||||||
|
)
|
||||||
|
elif tag == "insert":
|
||||||
|
for right in optimized_lines[j1:j2]:
|
||||||
|
rows.append(
|
||||||
|
f"<tr><td><pre></pre></td><td><pre>{_escape_html(right)}</pre></td></tr>"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not rows:
|
||||||
|
return "<table><tr><th>Original</th><th>Otimizada</th></tr></table>"
|
||||||
|
|
||||||
|
header = "<tr><th>Original</th><th>Otimizada</th></tr>"
|
||||||
|
body = "".join(rows)
|
||||||
|
return f"<table>{header}{body}</table>"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue