Skip to content

Assistente IA

O Doggy fornece um assistente IA global, presente em todas as páginas sob a forma de botão flutuante + painel deslizante lateral, profundamente integrado com as páginas através de um mecanismo de registo de contexto, e que suporta o ciclo de raciocínio ReAct e chamadas de ferramentas.

Visão geral

O assistente IA é construído sobre a stack symfony/ai-agent + symfony/ai-platform, ligando-se ao sistema de gateway LlmRouter da plataforma:

Client POST /api/admin/ai/chat  { context, message }
  → AiChatController
    → AiContextRegistry::get(context)
      → AiContextProviderInterface (e.g. ViewEditorAiContext)
        → AiAssistant::chat(roleCode, systemPrompt, toolProviders, message)
          → Agent::call(MessageBag, options)
            → AgentProcessor::processInput (injeta Tool)
            → LlmRouterPlatform::invoke → LlmRouter → LlmGatewayFactory
            → AgentProcessor::processOutput (ciclo ReAct)
            ← resposta em string

Entrada global

O painel do assistente IA é incluído incondicionalmente em templates/base.html.twig:

twig
<body>
    {% block body %}{% endblock %}
    {% include 'admin/ai_chat.html.twig' %}
</body>
  • Abrir/fechar: botão flutuante no canto inferior direito toggle-ai-chat / ai-chat-close
  • Entrada: Enter envia, Shift+Enter cria nova linha
  • Estado de carregamento: a entrada é desativada durante o pedido, exibindo "Pensando..."
  • Estilos: public/sunui/admin/ai_chat.css

Registo de contexto de página

Cada página regista o seu contexto no assistente através de window.__AI_CONTEXT__:

js
window.__AI_CONTEXT__ = {
    name: 'view_editor',                  // AiContextProviderInterface::getName() no backend
    buildPrompt: function(msg) {          // opcional, constrói a mensagem enviada ao backend
        return '[当前视图ID: xxx]\n\n' + msg;
    },
};

Exemplo de registo do editor de vistas:

twig
<script>
  window.__VIEW_ID__ = {{ id|json_encode|raw }};
  window.__AI_CONTEXT__ = {
      name: 'view_editor',
      buildPrompt: function(msg) {
          var vid = window.__VIEW_ID__;
          return vid ? '[当前视图ID: ' + vid + ']\n\n' + msg : msg;
      },
  };
</script>

Sistema de fornecedores de contexto

AiContextProviderInterface define o fornecedor de contexto:

php
namespace App\Service\AI\Runtime;

interface AiContextProviderInterface
{
    public function getName(): string;                    // identificador de contexto
    public function getRoleCode(): string;                // código de papel do LlmRouter
    public function getSystemPrompt(): string;            // prompt de sistema do Agent
    public function getToolProviders(): array;            // array de objetos Tool
}

Registo através da etiqueta app.ai_context:

yaml
App\Service\AI\Context\ViewEditorAiContext:
    tags:
        - { name: 'app.ai_context' }

Adicionar contexto de página

  1. Criar uma classe que implemente AiContextProviderInterface
  2. Adicionar tags: [{ name: 'app.ai_context' }] em services.yaml
  3. Definir window.__AI_CONTEXT__ = { name: 'your_name' } no template da página

Runtime do Agent

AiAssistant é uma fábrica de Agent genérica; cada chamada chat() cria uma instância de Agent independente, garantindo que não há poluição de estado:

php
$platform = new LlmRouterPlatform($this->router, $this->converter);
$toolbox = new Toolbox($toolProviders);

$agent = new Agent(
    platform: $platform,
    model: $roleCode,
    inputProcessors: [
        new SystemPromptInputProcessor($systemPrompt),
        new AgentProcessor($toolbox),
    ],
    outputProcessors: [
        new AgentProcessor($toolbox),
    ],
    name: 'ai-assistant',
);

Ciclo ReAct

AgentProcessor atua simultaneamente como processador de entrada e saída, implementando o ciclo de chamadas de ferramentas:

  • processInput: injeta os metadados das ferramentas do Toolbox
  • processOutput: quando o resultado é ToolCallResult:
    1. Adiciona o array de ToolCall ao MessageBag
    2. Executa ToolCall → escreve ToolResult de volta no MessageBag
    3. Invoca recursivamente até retornar TextResult

Sistema de ferramentas

Baseado no atributo #[AsTool] de symfony/ai-agent para marcar métodos de ferramenta:

php
use Symfony\AI\Agent\Toolbox\Attribute\AsTool;

class ViewEditorToolProvider
{
    #[AsTool(name: 'view.getInfo', description: '获取视图的完整信息')]
    public function getViewInfo(string $viewId): array { ... }

    #[AsTool(name: 'view.updateSectionConfig', description: '更新视图的布局配置')]
    public function updateSectionConfig(string $viewId, string $contentWidth, ...): array { ... }
}

Ferramentas atuais do editor de vistas

FerramentaFunção
view.getInfoObtém informações da vista (entidade, campos, layout)
view.updateSectionConfigAtualiza a configuração do layout
view.updateFieldConfigAtualiza a configuração dos campos
view.listEntityFieldsLista os campos da entidade

Princípios de design

  • Cada ferramenta é um método com uma única responsabilidade
  • Os nomes dos parâmetros coincidem com os do Schema JSON do #[AsTool] (mapeamento automático)
  • Retorna array (convertido em texto de resultado da ferramenta)

Endpoint da API

POST /api/admin/ai/chat

json
{
    "context": "view_editor",
    "message": "帮我改成三列布局"
}

Resposta de sucesso:

json
{
    "code": 200,
    "message": "success",
    "data": { "reply": "已修改为三列布局。" }
}

Ficheiros relacionados

FicheiroResponsabilidade
AiChatController.phpRecebe {context, message}, delega no Provider correspondente
AiContextRegistry.phpRecolhe os serviços com a etiqueta app.ai_context, indexa por nome
AiAssistant.phpFábrica de Agent genérica
LlmRouterPlatform.phpPonte PlatformInterface (MessageBag ↔ array)
ChatResultConverter.phpDados de resposta → TextResult/ToolCallResult
ViewEditorToolProvider.phpMétodos de ferramenta do editor de vistas
ChromeDevToolsToolProvider.phpFerramentas de depuração de browser CDP
ViewFileToolProvider.phpFerramentas de leitura/escrita de ficheiros de vista

Código aberto sob MIT | Copyright © 2026 Doggy