Initial commit
This commit is contained in:
164
docs/architecture.md
Normal file
164
docs/architecture.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Arquitetura
|
||||
|
||||
## Visão Geral
|
||||
|
||||
O Assistente Analítico é composto por três camadas principais: **interface** (Streamlit e FastAPI), **agente de IA** (LangGraph com Bedrock) e **dados** (DynamoDB).
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Interfaces │
|
||||
│ ┌────────────────────┐ ┌────────────────────────┐ │
|
||||
│ │ Streamlit (8501) │ │ FastAPI (8000) │ │
|
||||
│ │ front.py │ │ api.py │ │
|
||||
│ └────────┬───────────┘ └──────────┬─────────────┘ │
|
||||
│ │ │ │
|
||||
│ └──────────┬──────────────┘ │
|
||||
│ ▼ │
|
||||
│ orquestrador.main(query, history, model, base) │
|
||||
│ │ │
|
||||
│ ┌───────────────────▼──────────────────────────┐ │
|
||||
│ │ agent_bedrock — LangGraph │ │
|
||||
│ │ ┌────────┐ ┌───────┐ ┌────────────┐ │ │
|
||||
│ │ │ Model │───▶│Router │───▶│ Tools │ │ │
|
||||
│ │ │ Node │◀───│ │ │ Node │ │ │
|
||||
│ │ └────────┘ └───────┘ └────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────┐ │
|
||||
│ │ Serviços AWS │ │
|
||||
│ │ ┌──────────┐ ┌────────────────────────────┐ │ │
|
||||
│ │ │ Bedrock │ │ DynamoDB │ │ │
|
||||
│ │ │ (LLMs) │ │ (contexto + dados pré- │ │ │
|
||||
│ │ └──────────┘ │ processados) │ │ │
|
||||
│ │ └────────────────────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────┐ │
|
||||
│ │ Observabilidade │ │
|
||||
│ │ ┌──────────┐ ┌──────────────────────────┐ │ │
|
||||
│ │ │ Langfuse │ │ CloudWatch Logs │ │ │
|
||||
│ │ └──────────┘ └──────────────────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Módulos do Backend
|
||||
|
||||
O pacote `backend` é organizado por responsabilidade:
|
||||
|
||||
```
|
||||
backend/
|
||||
├── config.py ← variáveis de ambiente
|
||||
├── dynamo.py ← depende de config
|
||||
├── tools.py ← depende de config, dynamo
|
||||
├── agent_bedrock.py ← depende de config, tools
|
||||
└── orquestrador.py ← depende de config, dynamo, agent_bedrock
|
||||
```
|
||||
|
||||
Não há dependências circulares entre os módulos.
|
||||
|
||||
### `config.py`
|
||||
|
||||
Lê todas as variáveis de ambiente na inicialização e exporta como constantes:
|
||||
|
||||
| Variável | Descrição |
|
||||
|----------|-----------|
|
||||
| `TABLE` | Tabela DynamoDB |
|
||||
| `REGION` | Região AWS |
|
||||
| `AWS_ACCOUNT` | ID da conta AWS |
|
||||
| `SECRET_NAME` | Nome do secret no Secrets Manager |
|
||||
|
||||
### `dynamo.py`
|
||||
|
||||
- Instancia o cliente `dynamodb` (boto3) usando `REGION`
|
||||
- `get_secret()` — busca credenciais do Langfuse no Secrets Manager
|
||||
- Inicializa o objeto `langfuse` na carga do módulo
|
||||
- `get_contexto(dashboard: str) -> dict` — carrega contexto, filtro e itens disponíveis do DynamoDB para o dashboard informado
|
||||
|
||||
### `tools.py`
|
||||
|
||||
Define a classe `ReportTools`, instanciada por requisição com o mapeamento de IDs local → real.
|
||||
|
||||
```
|
||||
ReportTools(id_mapping: dict[str, str])
|
||||
├── get_variable_value(id, variable) — busca uma variável no DynamoDB
|
||||
├── get_variables_list(id) — lista as variáveis disponíveis para um ID
|
||||
└── as_tools() -> list[StructuredTool] — retorna as tools prontas para o agente
|
||||
```
|
||||
|
||||
| Tool (nome exposto ao LLM) | Método | Descrição |
|
||||
|---------------------------|--------|-----------|
|
||||
| `get_variable_value` | `get_variable_value(id, variable)` | Busca o valor de uma variável no DynamoDB para o ID informado |
|
||||
| `get_variable_list` | `get_variables_list(id)` | Lista as variáveis disponíveis para o ID informado |
|
||||
|
||||
Os IDs expostos ao LLM são locais (`id_1`, `id_2`, …). Internamente cada método converte o ID local para o ID real do DynamoDB via `self.id_mapping`. Por usar estado de instância em vez de variável global, múltiplas requisições simultâneas ficam completamente isoladas.
|
||||
|
||||
### `agent_bedrock.py`
|
||||
|
||||
- `AgentState` — TypedDict com `messages` e `current_step`
|
||||
- `create_bedrock_llm(model_id, region, tools)` — instancia `ChatBedrockConverse` e vincula as tools via `bind_tools`
|
||||
- `call_model(state, llm)` — nó do grafo: invoca o LLM
|
||||
- `call_tools(state, tools_map)` — nó do grafo: executa as tool calls usando o `tools_map` da requisição
|
||||
- `should_continue(state)` — roteador: `"tools"` se há tool_calls, `"end"` se não
|
||||
- `create_agent(inference_profile_arn, region, tools)` — constrói `tools_map = {t.name: t for t in tools}`, monta e compila o `StateGraph`
|
||||
|
||||
**Fluxo do Grafo:**
|
||||
|
||||
```
|
||||
SystemMessage + HumanMessage
|
||||
│
|
||||
▼
|
||||
┌─────────┐
|
||||
│ model │ ◄── LLM via Bedrock
|
||||
└────┬────┘
|
||||
│
|
||||
should_continue?
|
||||
├── tool_calls → ┌───────┐
|
||||
│ │ tools │ → executa tools → volta ao model
|
||||
│ └───────┘
|
||||
└── (fim) → [END]
|
||||
```
|
||||
|
||||
### `orquestrador.py`
|
||||
|
||||
Ponto de entrada da lógica de negócio. A função `main(user_query, history, model, base)`:
|
||||
|
||||
1. Chama `get_contexto(base)` para carregar o contexto do dashboard
|
||||
2. Constrói `id_mapping` (`id_1`, `id_2`, … → IDs reais do DynamoDB) e `local_items` (IDs locais → descrições)
|
||||
3. Instancia `ReportTools(id_mapping)` com o mapeamento isolado da requisição
|
||||
4. Monta o `SYSTEM_PROMPT` dinamicamente com contexto, regras de filtro, `local_items` e histórico
|
||||
5. Cria o agente via `create_agent(model, REGION, tools=report_tools.as_tools())`
|
||||
6. Invoca o agente com o estado inicial
|
||||
7. Agrega tokens de todos os `AIMessage` do estado final
|
||||
8. Retorna `response`, `input_tokens`, `output_tokens`, `total_tokens`
|
||||
|
||||
## Interfaces
|
||||
|
||||
### `front.py` — Streamlit (porta 8501)
|
||||
|
||||
- Importa `from backend import orquestrador`
|
||||
- Lista bases disponíveis consultando DynamoDB (`item_type_index`, `item_type = "contexto"`)
|
||||
- Seleção de modelo LLM e base via `st.selectbox`
|
||||
- Histórico de conversas em `session_state`
|
||||
- Efeito de digitação caractere a caractere
|
||||
- Exibe consumo de tokens por resposta
|
||||
|
||||
### `api.py` — FastAPI (porta 8000)
|
||||
|
||||
- Importa `from .backend import orquestrador`
|
||||
- `GET /` — health check
|
||||
- `POST /agent` — recebe `QueryRequest`, chama `orquestrador.main()`, retorna `QueryResponse`
|
||||
|
||||
## Modelos LLM Suportados
|
||||
|
||||
| Modelo | Provider | Prefixo de Rota |
|
||||
|--------|----------|-----------------|
|
||||
| `anthropic.claude-haiku-4-5-20251001-v1:0` | Anthropic | `us` |
|
||||
| `anthropic.claude-sonnet-4-5-20250929-v1:0` | Anthropic | `global` |
|
||||
| `meta.llama4-maverick-17b-instruct-v1:0` | Meta | `us` |
|
||||
| `meta.llama4-scout-17b-instruct-v1:0` | Meta | `us` |
|
||||
| `amazon.nova-lite-v1:0` | Amazon | `us` |
|
||||
| `amazon.nova-pro-v1:0` | Amazon | `us` |
|
||||
| `amazon.nova-2-lite-v1:0` | Amazon | `global` |
|
||||
|
||||
Todos acessados via AWS Bedrock inference profiles cross-region. O ARN é construído dinamicamente com `REGION` e `AWS_ACCOUNT`.
|
||||
Reference in New Issue
Block a user