Логи диалогов с корпоративным AI-ассистентом — это одновременно самый ценный и самый опасный актив, который у тебя появляется после запуска сервиса. Ценный — потому что по логам видно, чем реально пользуются сотрудники, где модель ошибается, куда уходит нагрузка. Опасный — потому что в чат с ассистентом люди пишут то же, что написали бы коллеге: черновики контрактов, куски персональных данных клиентов, внутренние пароли «чтобы модель проверила синтаксис», медицинские данные сотрудников при обсуждении больничных. Если логи хранятся без продуманной политики, ты рискуешь превратить AI-сервис в самую большую утечку данных в истории компании.

Разберём, что стоит хранить, что не стоит, и как выстроить хранение логов на srv-ai01 так, чтобы соблюсти и приватность, и требования по разбору инцидентов.

Зачем вообще хранить логи диалогов

Прежде чем резать логи «для приватности», стоит понять, зачем они нужны:

  • разбор инцидентов — если агент выдал вредный или ошибочный ответ, нужно понять, на основе какого промпта;
  • аудит безопасности — обнаружение попыток prompt injection, экспорта чувствительных данных, злоупотреблений;
  • улучшение качества — анализ, какие запросы модель обрабатывает плохо, чтобы дообучать промпты или переключать модель;
  • учёт использования — тот самый подсчёт токенов и активности по отделам.

Для каждой цели набор нужных данных разный, и это важно: для учёта токенов не нужно хранить текст диалога, а для аудита безопасности не нужно хранить его вечно.

Уровни детализации логов

Разумно вести не один общий лог, а несколько слоёв с разной степенью детализации и разным сроком хранения.

Уровень 1 — метаданные (хранить долго, 12+ месяцев):
  timestamp, user_id, model, token_count, latency_ms, status_code,
  plugin_used (web_search / code_interpreter / none)

Уровень 2 — содержимое диалога (хранить ограниченно, 30-90 дней):
  полный текст запроса и ответа, с маскированием PII

Уровень 3 — security-события (хранить долго, 12+ месяцев):
  сработавшие фильтры prompt injection, попытки доступа
  к запрещённым инструментам, аномалии по rate limit

Такое разделение позволяет держать полный текст диалогов недолго — ровно столько, сколько нужно для разбора инцидентов и улучшения качества, — а метаданные и security-события хранить дольше, потому что они сами по себе не содержат чувствительного контента.

Маскирование персональных данных в логах

Прежде чем логировать полный текст диалога даже на 30-90 дней, стоит прогнать его через маскирование PII. Простой вариант — regex-based фильтр для очевидных паттернов:

import re

PII_PATTERNS = {
    "email": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",
    "phone": r"\+?\d{1,3}[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}",
    "card": r"\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b",
}

def mask_pii(text: str) -> str:
    for label, pattern in PII_PATTERNS.items():
        text = re.sub(pattern, f"[{label.upper()}_REDACTED]", text)
    return text

Для более надёжного результата регулярки стоит дополнить отдельной небольшой NER-моделью (даже локальной, вроде spaCy с русской моделью), которая распознаёт имена, адреса и другие сущности, которые сложно поймать регулярным выражением. Маскирование лучше применять на этапе записи лога, а не постфактум — если сырые данные хотя бы раз попали на диск в незамаскированном виде, «постфактум» уже не поможет.

Хранение и доступ к логам

Логи с содержимым диалогов должны храниться отдельно от общей инфраструктуры логирования компании (той же, куда льются логи веб-сервера или CI/CD), потому что доступ к ним требует более узкого круга людей.

# структура на srv-ai01
/var/log/ai-service/
  metadata/          # уровень 1, права 640, широкий доступ для DevOps
  conversations/      # уровень 2, права 600, доступ только security-team
  security-events/    # уровень 3, права 640, доступ DevOps + security

Для ротации и автоматического удаления логов уровня 2 по истечении срока хранения подойдёт простой logrotate или cron-задача:

# /etc/cron.d/ai-conversation-retention
0 3 * * * root find /var/log/ai-service/conversations -type f -mtime +90 -delete

Отдельно стоит подумать про право сотрудника на удаление собственных диалогов по запросу — это уже вопрос не только технический, но и юридический, особенно если компания работает с персональными данными под 152-ФЗ или аналогичным регулированием. Технически проще всего реализовать это через привязку каждого лога к user_id и написать простой скрипт удаления по запросу.

Что не стоит хранить вообще

  • сырые API-ключи и пароли, которые пользователь мог случайно вставить в чат — их стоит детектить тем же PII-фильтром и вырезать до записи, а не после;
  • вложенные файлы целиком в общем логе — если пользователь прикрепил документ, разумнее хранить хэш и метаданные файла, а не его содержимое вместе с остальными логами;
  • содержимое диалогов из сессий, помеченных как «приватные» или «инкогнито», если такой режим у тебя предусмотрен в Open WebUI — в этом случае не должно оставаться и следа в уровне 2, только агрегированные метаданные уровня 1.

Согласие пользователей и прозрачность

Отдельный, часто упускаемый момент — сотрудники должны заранее знать, что их диалоги с AI-ассистентом логируются, в каком объёме и на какой срок. Это не только вопрос доверия внутри компании, но и юридическая необходимость, если политика обработки персональных данных требует информированного согласия. Практическое решение — короткое уведомление при первом входе в Open WebUI с ссылкой на политику хранения логов, и режим «приватного чата» для случаев, когда сотруднику нужно обсудить с ассистентом что-то заведомо не подлежащее длительному хранению.

# баннер согласия, показывается один раз при первом входе
ENABLE_SIGNUP_CONSENT_BANNER=true
CONSENT_BANNER_TEXT=Диалоги с ассистентом сохраняются для аудита
  безопасности и повышения качества сервиса. Полный текст диалогов
  хранится 90 дней. Подробнее: itpages.lab.local/policies/ai-logging

Режим приватного чата стоит реализовать так, чтобы в него не попадали метаданные уровня 2 вообще, но при этом сохранялись базовые метаданные уровня 1 (сам факт обращения, количество токенов) — это нужно для честного учёта нагрузки на srv-ai01, не раскрывая содержимого. Важно явно предупреждать, что приватный режим не отменяет фильтры безопасности: попытки prompt injection или запросы к запрещённым инструментам всё равно должны логироваться в security-events, даже из приватной сессии, иначе этот режим превращается в дыру для обхода контроля.

Экспорт логов для внешнего аудита

Если компания подпадает под внешний комплаенс-аудит (ISO 27001, SOC 2 или отраслевые требования), полезно заранее продумать формат экспорта логов security-событий в читаемом для аудитора виде, не раскрывая при этом содержимого чувствительных диалогов.

# экспорт агрегированной статистики без содержимого диалогов
SELECT
    date_trunc('day', created_at) AS day,
    user_id,
    event_type,
    count(*) AS occurrences
FROM security_events
WHERE created_at >= now() - interval '90 days'
GROUP BY 1, 2, 3
ORDER BY 1 DESC;

Такой отчёт показывает аудитору, что система контролируется и события фиксируются, но не требует раскрытия персональных данных сотрудников или клиентов, упомянутых в самих диалогах.

Разные политики хранения для разных типов агентов

Не все агенты одинаково чувствительны с точки зрения хранения логов. Внутренний ассистент для код-ревью, скорее всего, не работает с персональными данными вообще, тогда как агент поддержки клиентов почти гарантированно сталкивается с ними в каждом втором диалоге. Разумно вести не единую политику на все случаи, а профиль хранения для каждого класса агентов.

# профили хранения логов по типу агента
retention_profiles:
  code-review-assistant:
    conversations_days: 180   # низкая чувствительность, дольше хранение
    pii_masking: false        # PII почти не встречается в коде

  support-assistant:
    conversations_days: 30    # высокая чувствительность, короче срок
    pii_masking: true
    pii_strict_mode: true     # более агрессивное маскирование

  analytics-assistant:
    conversations_days: 60
    pii_masking: true

Такая дифференциация требует чуть больше настройки на старте, зато отражает реальный профиль риска каждого агента, вместо универсального компромисса, который для одних агентов избыточно строгий, а для других недостаточно осторожный.

Частые ошибки и как их избежать

  • Один общий лог без разделения по уровням чувствительности. Итог — либо хранишь всё вечно с огромным риском утечки, либо удаляешь всё быстро и теряешь возможность разбирать инциденты. Раздели логи на слои с самого начала.
  • Маскирование PII применяется постфактум скриптом раз в неделю. Всю неделю чувствительные данные лежат на диске в открытом виде. Маскируй на этапе записи, до того как данные попадут на диск.
  • Доступ к логам диалогов есть у всей DevOps-команды «на всякий случай». Чем шире круг доступа, тем выше риск внутренней утечки. Ограничивай доступ к содержимому диалогов явным списком людей с обоснованной необходимостью.

Логи и обучение на данных компании

Соблазн использовать накопленные логи диалогов для дообучения собственной модели (fine-tuning) под специфику компании понятен — это потенциально улучшает качество ответов. Но здесь стоит быть особенно осторожным: если в логах остались персональные данные клиентов или сотрудников, модель, обученная на них, рискует «запомнить» и впоследствии случайно воспроизвести эти данные в ответах другим пользователям.

  • Используй для fine-tuning только логи, прошедшие полное маскирование PII, и в идеале — отдельно проверенные человеком перед включением в обучающий набор;
  • Никогда не включай в обучающий набор диалоги из сессий, помеченных как приватные, даже если формально срок их хранения ещё не истёк;
  • Получи явное согласие на использование диалогов для обучения отдельно от согласия на их хранение — это разные по последствиям действия, и объединять их в одном пункте политики не стоит.

Практический пример структуры записи лога

Для наглядности — как может выглядеть единая запись, объединяющая все три уровня детализации в одном событии, прежде чем она распределяется по соответствующим хранилищам:

{
  "timestamp": "2026-08-28T14:32:10Z",
  "user_id": "e.ivanova",
  "session_id": "a1b2c3d4",
  "model": "support-assistant",
  "token_count": {"input": 340, "output": 128},
  "latency_ms": 1840,
  "plugin_used": "web_search",
  "content": {
    "request": "[замаскировано, хранится 90 дней]",
    "response": "[замаскировано, хранится 90 дней]"
  },
  "security_flags": {
    "injection_detected": false,
    "pii_masked_count": 2
  }
}

Такая структура позволяет одним запросом получить метаданные для дашборда учёта нагрузки (см. статью про ограничение доступа и учёт токенов), не поднимая при этом чувствительное содержимое диалога, доступ к которому строго ограничен.

Что дальше

Безопасность и эксплуатация AI-инфраструктуры — вот с чем ещё стоит разобраться: