Skip to content

AI 어시스턴트

Doggy는 전역 AI 어시스턴트를 제공하며, 플로팅 버튼 + 사이드 패널 형태로 모든 페이지에 존재하고 컨텍스트 등록 메커니즘을 통해 페이지와 심층 통합되며 ReAct 추론 루프와 도구 호출을 지원합니다.

개요

AI 어시스턴트는 symfony/ai-agent + symfony/ai-platform 기술 스택으로 구축되어 플랫폼 자체 LlmRouter 게이트웨이 체계와 연동됩니다:

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 (Tool 주입)
            → LlmRouterPlatform::invoke → LlmRouter → LlmGatewayFactory
            → AgentProcessor::processOutput (ReAct 루프)
            ← string response

전역 진입점

AI 어시스턴트 패널은 templates/base.html.twig에서 무조건적으로 포함됩니다:

twig
<body>
    {% block body %}{% endblock %}
    {% include 'admin/ai_chat.html.twig' %}
</body>
  • 열기/닫기: 우하단 플로팅 버튼 toggle-ai-chat / ai-chat-close
  • 입력: Enter 전송, Shift+Enter 줄바꿈
  • 로딩 상태: 요청 중 입력 비활성화, "생각 중..." 표시
  • 스타일: public/sunui/admin/ai_chat.css

페이지 컨텍스트 등록

각 페이지는 window.__AI_CONTEXT__를 통해 어시스턴트에 컨텍스트를 등록합니다:

js
window.__AI_CONTEXT__ = {
    name: 'view_editor',                  // 백엔드 AiContextProviderInterface::getName()
    buildPrompt: function(msg) {          // 선택 사항, 백엔드로 전송할 메시지 구성
        return '[현재 뷰 ID: xxx]\n\n' + msg;
    },
};

뷰 편집기 등록 예시:

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>

컨텍스트 제공자 시스템

AiContextProviderInterface가 컨텍스트 제공자를 정의합니다:

php
namespace App\Service\AI\Runtime;

interface AiContextProviderInterface
{
    public function getName(): string;                    // 컨텍스트 식별자
    public function getRoleCode(): string;                // LlmRouter 역할 코드
    public function getSystemPrompt(): string;            // Agent 시스템 프롬프트
    public function getToolProviders(): array;            // Tool 객체 배열
}

app.ai_context 태그로 등록:

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

새 페이지 컨텍스트 추가

  1. AiContextProviderInterface를 구현하는 클래스 생성
  2. services.yamltags: [{ name: 'app.ai_context' }] 추가
  3. 페이지 템플릿에서 window.__AI_CONTEXT__ = { name: 'your_name' } 설정

Agent 런타임

AiAssistant는 범용 Agent 팩토리로, chat() 호출마다 독립된 Agent 인스턴스를 생성하여 상태 오염을 방지합니다:

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',
);

ReAct 루프

AgentProcessor는 입력/출력 프로세서를 겸하며 도구 호출 루프를 구현합니다:

  • processInput: Toolbox의 Tool 메타데이터 주입
  • processOutput: 결과가 ToolCallResult인 경우:
    1. ToolCall 배열을 MessageBag에 추가
    2. ToolCall 실행 → ToolResult를 MessageBag에 기록
    3. TextResult가 반환될 때까지 재귀 호출

도구 체계

symfony/ai-agent#[AsTool] 속성으로 도구 메서드를 표시합니다:

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 { ... }
}

현재 뷰 편집기 도구

Tool기능
view.getInfo뷰 정보 가져오기(엔티티, 필드, 레이아웃)
view.updateSectionConfig레이아웃 설정 업데이트
view.updateFieldConfig필드 설정 업데이트
view.listEntityFields엔티티 필드 나열

설계 원칙

  • 각 도구는 단일 책임 메서드
  • 파라미터명은 #[AsTool] JSON Schema 파라미터명과 일치(자동 매핑)
  • array 반환(도구 결과 텍스트로 변환)

API 엔드포인트

POST /api/admin/ai/chat

json
{
    "context": "view_editor",
    "message": "3열 레이아웃으로 바꿔줘"
}

성공 응답:

json
{
    "code": 200,
    "message": "success",
    "data": { "reply": "3열 레이아웃으로 수정했습니다." }
}

관련 파일

파일역할
AiChatController.php{context, message} 수신, 해당 Provider에 위임
AiContextRegistry.phpapp.ai_context 태그 서비스 수집, name 기준 색인
AiAssistant.php범용 Agent 팩토리
LlmRouterPlatform.phpPlatformInterface 브리지 (MessageBag ↔ 배열)
ChatResultConverter.php응답 데이터 → TextResult/ToolCallResult
ViewEditorToolProvider.php뷰 편집기 Tool 메서드
ChromeDevToolsToolProvider.phpCDP 브라우저 디버깅 도구
ViewFileToolProvider.php뷰 파일 읽기/쓰기 도구

MIT 라이선스 오픈소스 | Copyright © 2026 Doggy