Статьи
Архитектура 2 мин 146

Как устроены 24 AI-агента в HRMS на Rails 8

Архитектура мульти-провайдерной AI-системы: per-task модели, budget guard, audit log. Реальный production-опыт.

Проблема

Большинство туториалов показывают «подключи OpenAI API и вызови chat completion». В реальности нужно:

  • Разные модели для разных задач (GPT-4o для анализа резюме, Haiku для саммаризации)
  • Hard cap на бюджет — чтобы джуниор-HR не потратил $500 за ночь
  • Полный audit log каждого вызова с cost tracking
  • Fallback при недоступности провайдера
  • Возможность переключить на self-hosted (Ollama, vLLM) без изменения кода

Архитектура

AiProvider — абстракция над API

class AiProvider
  PROVIDERS = {
    openai: AiProviders::OpenAi,
    anthropic: AiProviders::Anthropic,
    openrouter: AiProviders::OpenRouter,
    ollama: AiProviders::Ollama,
    custom: AiProviders::Custom,
  }.freeze

  def self.for(task_name)
    config = AiTaskConfig.find_by(task: task_name) || default_config
    PROVIDERS[config.provider.to_sym].new(config)
  end
end

Каждый провайдер реализует один метод #chat(messages:, **opts) и возвращает стандартный AiResponse.

Per-task конфигурация

В /settings/ai HR выбирает модель для каждой задачи:

Задача Модель Почему
analyze_resume gpt-4o Нужен reasoning для red flags
summarize_interview claude-haiku Быстро и дёшево для TL;DR
company_bootstrap gpt-4o-mini+ Сложный meta-промпт с JSON
dictionary_seed Любая Простая генерация списка

AiBudgetGuard

class AiBudgetGuard
  HARD_CAP_MULTIPLIER = 2.0

  def self.allow?(company)
    return true if company.ai_monthly_budget_usd.zero?
    current_spend = AiRun.where(company: company)
                        .where("created_at >= ?", Time.current.beginning_of_month)
                        .sum(:cost_usd)
    current_spend < company.ai_monthly_budget_usd * HARD_CAP_MULTIPLIER
  end
end

Guard проверяется перед каждым RunAiTaskJob. Кэшируется на 60 секунд — баланс между точностью и производительностью.

Audit Log

Каждый AI-вызов создаёт AiRun:

AiRun.create!(
  company: Current.company,
  user: Current.user,
  task: "analyze_resume",
  provider: "openai",
  model: "gpt-4o",
  input_tokens: response.input_tokens,
  output_tokens: response.output_tokens,
  cost_usd: response.cost,
  duration_ms: elapsed,
  status: :success
)

В дашборде — real-time график расходов по задачам и моделям.

24 агента по категориям

Найм (7): analyzeresume, generateassignment, questionsfor, summarizeinterview, comparecandidates, recommend, offerletter

Удержание (6): burnoutbrief, suggestleavewindow, kpibrief, kpiteambrief, meetingagenda, compensationreview, exitriskbrief

Онбординг (7): onboardingplan, welcomeletter, mentormatch, probationreview, knowledgetransferplan, exitinterviewbrief, replacement_brief

Документы (4): documentsummary, documentextractassist, dictionaryseed, company_bootstrap

Выводы

  • Абстракция провайдера окупается с первого дня — переключение модели занимает 30 секунд в UI
  • Budget guard обязателен — без него первый же любопытный HR-менеджер сожжёт месячный бюджет за час
  • Audit log — не роскошь, а необходимость для compliance (GDPR, 152-ФЗ)
  • Self-hosted fallback (Ollama) спасает при downtime OpenAI — а он случается

Комментарии (0)