gb/prompts/switcher.md

15 KiB

SWITCHER Feature - Response Format Modifiers

Overview

Add a switcher interface that allows users to toggle response modifiers that influence how the AI generates responses. Unlike suggestions (which are one-time actions), switchers are persistent toggles that remain active until deactivated.

Location

botui/ui/suite/chat/ - alongside existing suggestion buttons

Syntax

Standard Switcher (predefined prompt)

ADD SWITCHER "tables" AS "Tabelas"

Custom Switcher (with custom prompt)

ADD SWITCHER "sempre mostrar 10 perguntas" AS "Mostrar Perguntas"

What Switcher Does

The switcher:

  1. Injects the prompt into every LLM request
  2. The prompt can be:
    • Standard: References a predefined prompt by ID ("tables", "cards", etc.)
    • Custom: Any custom instruction string ("sempre mostrar 10 perguntas")
  3. Influences the AI response format
  4. Persists until toggled OFF

Available Standard Switchers

ID Label Color Description
tables Tabelas #4CAF50 Format responses as tables
infographic Infográfico #2196F3 Visual, graphical representations
cards Cards #FF9800 Card-based layout
list Lista #9C27B0 Bulleted lists
comparison Comparação #E91E63 Side-by-side comparisons
timeline Timeline #00BCD4 Chronological ordering
markdown Markdown #607D8B Standard markdown
chart Gráfico #F44336 Charts and diagrams

Predefined Prompts (Backend)

Each standard ID maps to a predefined prompt in the backend:

ID: tables
Prompt: "REGRAS DE FORMATO: SEMPRE retorne suas respostas em formato de tabela HTML usando <table>, <thead>, <tbody>, <tr>, <th>, <td>. Cada dado deve ser uma célula. Use cabeçalhos claros na primeira linha. Se houver dados numéricos, alinhe à direita. Se houver texto, alinhe à esquerda. Use cores sutis em linhas alternadas (nth-child). NÃO use markdown tables, use HTML puro."

ID: infographic
Prompt: "REGRAS DE FORMATO: Crie representações visuais HTML usando SVG, progress bars, stat cards, e elementos gráficos. Use elementos como: <svg> para gráficos, <div style="width:X%;background:color"> para barras de progresso, ícones emoji, badges coloridos. Organize informações visualmente com grids, flexbox, e espaçamento. Inclua legendas e rótulos visuais claros."

ID: cards
Prompt: "REGRAS DE FORMATO: Retorne informações em formato de cards HTML. Cada card deve ter: <div class="card" style="border:1px solid #ddd;border-radius:8px;padding:16px;margin:8px;box-shadow:0 2px 4px rgba(0,0,0,0.1)">. Dentro do card use: título em <h3> ou <strong>, subtítulo em <p> style="color:#666", ícone emoji ou ícone SVG no topo, badges de status. Organize cards em grid usando display:grid ou flex-wrap."

ID: list
Prompt: "REGRAS DE FORMATO: Use apenas listas HTML: <ul> para bullets e <ol> para números numerados. Cada item em <li>. Use sublistas aninhadas quando apropriado. NÃO use parágrafos de texto, converta tudo em itens de lista. Adicione ícones emoji no início de cada <li> quando possível. Use classes CSS para estilização: .list-item, .sub-list."

ID: comparison
Prompt: "REGRAS DE FORMATO: Crie comparações lado a lado em HTML. Use grid de 2 colunas: <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px">. Cada lado em uma <div class="comparison-side"> com borda colorida distinta. Use headers claros para cada lado. Adicione seção de "Diferenças Chave" com bullet points. Use cores contrastantes para cada lado (ex: azul vs laranja). Inclua tabela de comparação resumida no final."

ID: timeline
Prompt: "REGRAS DE FORMATO: Organize eventos cronologicamente em formato de timeline HTML. Use <div class="timeline"> com border-left vertical. Cada evento em <div class="timeline-item"> com: data em <span class="timeline-date" style="font-weight:bold;color:#666">, título em <h3>, descrição em <p>. Adicione círculo indicador na timeline line. Ordene do mais antigo para o mais recente. Use espaçamento claro entre eventos."

ID: markdown
Prompt: "REGRAS DE FORMATO: Use exclusivamente formato Markdown padrão. Sintaxe permitida: **negrito**, *itálico*, `inline code`, ```bloco de código```, # cabeçalhos, - bullets, 1. números, [links](url), ![alt](url), | tabela | markdown |. NÃO use HTML tags exceto para blocos de código. Siga estritamente a sintaxe CommonMark."

ID: chart
Prompt: "REGRAS DE FORMATO: Crie gráficos e diagramas em HTML SVG. Use elementos SVG: <svg width="X" height="Y">, <line> para gráficos de linha, <rect> para gráficos de barra, <circle> para gráficos de pizza, <path> para gráficos de área. Inclua eixos com labels, grid lines, legendas. Use cores distintas para cada série de dados (ex: vermelho, azul, verde). Adicione tooltips com valores ao hover. Se o usuário pedir gráfico de pizza com "pizza vermelha", use fill="#FF0000" no SVG."

UI Design

HTML Structure

<div class="switchers-container" id="switchers">
    <div class="switchers-label">Formato:</div>
    <div class="switchers-chips" id="switchersChips">
        <!-- Switcher chips will be rendered here -->
    </div>
</div>

Placement

Position the switchers container above the suggestions container:

<footer>
    <div class="switchers-container" id="switchers"></div>
    <div class="suggestions-container" id="suggestions"></div>
    <!-- ... existing form ... -->
</footer>

CSS Styling

Container

.switchers-container {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 16px;
    flex-wrap: wrap;
    background: rgba(0, 0, 0, 0.02);
    border-top: 1px solid rgba(0, 0, 0, 0.05);
}

.switchers-label {
    font-size: 13px;
    font-weight: 600;
    color: #666;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

Switcher Chips (Toggle Buttons)

.switchers-chips {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.switcher-chip {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 20px;
    border: 2px solid transparent;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
    background: rgba(0, 0, 0, 0.05);
    color: #666;
    user-select: none;
}

.switcher-chip:hover {
    background: rgba(0, 0, 0, 0.08);
    transform: translateY(-1px);
}

.switcher-chip.active {
    border-color: currentColor;
    background: currentColor;
    color: white;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.switcher-chip-icon {
    font-size: 14px;
}

JavaScript Implementation

State Management

// Track active switchers
var activeSwitchers = new Set();

// Switcher definitions (from ADD SWITCHER commands in start.bas)
var switcherDefinitions = [
    {
        id: 'tables',
        label: 'Tabelas',
        icon: '📊',
        color: '#4CAF50'
    },
    {
        id: 'infographic',
        label: 'Infográfico',
        icon: '📈',
        color: '#2196F3'
    },
    {
        id: 'cards',
        label: 'Cards',
        icon: '🃏',
        color: '#FF9800'
    },
    {
        id: 'list',
        label: 'Lista',
        icon: '📋',
        color: '#9C27B0'
    },
    {
        id: 'comparison',
        label: 'Comparação',
        icon: '⚖️',
        color: '#E91E63'
    },
    {
        id: 'timeline',
        label: 'Timeline',
        icon: '📅',
        color: '#00BCD4'
    },
    {
        id: 'markdown',
        label: 'Markdown',
        icon: '📝',
        color: '#607D8B'
    },
    {
        id: 'chart',
        label: 'Gráfico',
        icon: '📉',
        color: '#F44336'
    }
];

Render Switchers

function renderSwitchers() {
    var container = document.getElementById("switcherChips");
    if (!container) return;

    container.innerHTML = switcherDefinitions.map(function(sw) {
        var isActive = activeSwitchers.has(sw.id);
        return (
            '<div class="switcher-chip' + (isActive ? ' active' : '') + '" ' +
            'data-switch-id="' + sw.id + '" ' +
            'style="--switcher-color: ' + sw.color + '; ' +
            (isActive ? 'color: ' + sw.color + ' background: ' + sw.color + '; ' : '') +
            '">' +
            '<span class="switcher-chip-icon">' + sw.icon + '</span>' +
            '<span>' + sw.label + '</span>' +
            '</div>'
        );
    }).join('');

    // Add click handlers
    container.querySelectorAll('.switcher-chip').forEach(function(chip) {
        chip.addEventListener('click', function() {
            toggleSwitcher(this.getAttribute('data-switch-id'));
        });
    });
}

Toggle Handler

function toggleSwitcher(switcherId) {
    if (activeSwitchers.has(switcherId)) {
        activeSwitchers.delete(switcherId);
    } else {
        activeSwitchers.add(switcherId);
    }
    renderSwitchers();
}

Message Enhancement

When sending a user message, prepend active switcher prompts:

function sendMessage(messageContent) {
    // ... existing code ...

    var content = messageContent || input.value.trim();
    if (!content) return;

    // Prepend active switcher prompts
    var enhancedContent = content;
    if (activeSwitchers.size > 0) {
        // Get prompts for active switchers from backend
        var activePrompts = [];
        activeSwitchers.forEach(function(id) {
            // Backend has predefined prompts for each ID
            activePrompts.push(getSwitcherPrompt(id));
        });

        // Inject prompts before user message
        if (activePrompts.length > 0) {
            enhancedContent = activePrompts.join('\n\n') + '\n\n---\n\n' + content;
        }
    }

    // Send enhanced content
    addMessage("user", content);

    if (ws && ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
            bot_id: currentBotId,
            user_id: currentUserId,
            session_id: currentSessionId,
            channel: "web",
            content: enhancedContent,
            message_type: MessageType.USER,
            timestamp: new Date().toISOString(),
        }));
    }
}

function getSwitcherPrompt(switcherId) {
    // Get predefined prompt from backend or API
    // For example, tables ID maps to:
    // "REGRAS DE FORMATO: SEMPRE retorne suas respostas em formato de tabela HTML..."
    var switcher = switcherDefinitions.find(function(s) { return s.id === switcherId; });
    if (!switcher) return "";

    // This could be fetched from backend or stored locally
    return SWITCHER_PROMPTS[switcherId] || "";
}

Bot Integration (start.bas)

The bot receives the switcher prompt injected into the user message and simply passes it to the LLM.

Example in start.bas

REM Switcher prompts are automatically injected by frontend
REM Just pass user_input to LLM - no parsing needed!

REM If user types: "mostra os cursos"
REM And "Tabelas" switcher is active
REM Frontend sends: "REGRAS DE FORMATO: SEMPRE retorne suas respostas em formato de tabela HTML... --- mostra os cursos"

REM Bot passes directly to LLM:
response$ = CALL_LLM(user_input)

REM The LLM will follow the REGRAS DE FORMATO instructions

Multiple Active Switchers

When multiple switchers are active, all prompts are injected:

REM Frontend injects multiple REGRAS DE FORMATO blocks
REM Example with "Tabelas" and "Gráfico" active:
REM
REM "REGRAS DE FORMATO: SEMPRE retorne suas respostas em formato de tabela HTML...
REM  REGRAS DE FORMATO: Crie gráficos e diagramas em HTML SVG...
REM  ---
REM  mostra os dados de vendas"

REM Bot passes to LLM:
response$ = CALL_LLM(user_input)

Implementation Steps

  1. Create prompts/switcher.md (this file)
  2. Define predefined prompts in backend (map IDs to prompt strings)
  3. Add HTML structure to chat.html (switchers container)
  4. Add CSS styles to chat.css (switcher chip styles)
  5. Add switcher definitions to chat.js
  6. Implement renderSwitchers() function
  7. Implement toggleSwitcher() function
  8. Modify sendMessage() to prepend switcher prompts
  9. Update salesianos bot start.bas to use ADD SWITCHER commands
  10. Test locally with all switcher options
  11. Verify multiple switchers can be active simultaneously
  12. Test persistence across page refreshes (optional - localStorage)

Testing Checklist

  • Switchers appear above suggestions
  • Switchers are colorful and match their defined colors
  • Clicking a switcher toggles it on/off
  • Multiple switchers can be active simultaneously
  • Active switchers have distinct visual state (border, background, shadow)
  • Formatted responses match the selected format
  • Toggling off removes the format modifier
  • Works with empty active switchers (normal response)
  • Works in combination with suggestions
  • Responsive design on mobile devices

Files to Modify

  1. botui/ui/suite/chat/chat.html - Add switcher container HTML
  2. botui/ui/suite/chat/chat.css - Add switcher styles
  3. botui/ui/suite/chat/chat.js - Add switcher logic
  4. botserver/bots/salesianos/start.bas - Add ADD SWITCHER commands

Example start.bas

USE_WEBSITE("https://salesianos.br", "30d")

USE KB "carta"
USE KB "proc"

USE TOOL "inscricao"
USE TOOL "consultar_inscricao"
USE TOOL "agendamento_visita"
USE TOOL "informacoes_curso"
USE TOOL "documentos_necessarios"
USE TOOL "contato_secretaria"
USE TOOL "calendario_letivo"

ADD_SUGGESTION_TOOL "inscricao" AS "Fazer Inscrição"
ADD_SUGGESTION_TOOL "consultar_inscricao" AS "Consultar Inscrição"
ADD_SUGGESTION_TOOL "agendamento_visita" AS "Agendar Visita"
ADD_SUGGESTION_TOOL "informacoes_curso" AS "Informações de Cursos"
ADD_SUGGESTION_TOOL "documentos_necessarios" AS "Documentos Necessários"
ADD_SUGGESTION_TOOL "contato_secretaria" AS "Falar com Secretaria"
ADD_SUGGESTION_TOOL "segunda_via" AS "Segunda Via de Boleto"
ADD_SUGGESTION_TOOL "calendario_letivo" AS "Calendário Letivo"
ADD_SUGGESTION_TOOL "outros" AS "Outros"

ADD SWITCHER "tables" AS "Tabelas"
ADD SWITCHER "infographic" AS "Infográfico"
ADD SWITCHER "cards" AS "Cards"
ADD SWITCHER "list" AS "Lista"
ADD SWITCHER "comparison" AS "Comparação"
ADD SWITCHER "timeline" AS "Timeline"
ADD SWITCHER "markdown" AS "Markdown"
ADD SWITCHER "chart" AS "Gráfico"

TALK "Olá! Sou o assistente virtual da Escola Salesiana. Como posso ajudá-lo hoje com inscrições, visitas, informações sobre cursos, documentos ou calendário letivo? Você pode também escolher formatos de resposta acima da caixa de mensagem."

Notes

  • Switchers are persistent until deactivated
  • Multiple switchers can be active at once
  • Switcher prompts are prepended to user messages with "---" separator
  • The backend (LLM) should follow these format instructions
  • UI should provide clear visual feedback for active switchers
  • Color coding helps users quickly identify active formats
  • Standard switchers use predefined prompts in backend
  • Custom switchers allow any prompt string to be injected