Files

3.8 KiB

email-classification Specification

Purpose

Классификация писем локальной LLM: после скачивания письма модель определяет тип письма (информационное, требует срочного ответа, содержит задачу, содержит встречу) и записывает тег + обоснование в frontmatter файла email.md. Обработка приватна — модель Qwen3:8b запущена локально через Ollama, текст письма не покидает хост.

Requirements

Requirement: Классификация каждого нового письма

Каждое письмо, заархивированное mail_archive.py, MUST быть классифицировано локальной моделью не позднее одного прохода классификатора после архивации.

Scenario: Новое письмо после архивации

  • WHEN mail_archive.py сохранил новое письмо в /opt/hermes/email/**/email.md без поля classification
  • THEN email_classifier.py обработает его и запишет в frontmatter поле classification с одним из значений: info, urgent, task, meeting (или комбинацию через запятую)

Requirement: Приватность обработки

Классификация MUST выполняться локальной моделью (Qwen3:8b через Ollama на localhost:11434) и MUST NOT отправлять текст письма в облачные API.

Scenario: Локальная модель доступна

  • WHEN классификатор запущен
  • THEN запросы к LLM идут только на http://localhost:11434 (Ollama), никаких внешних HTTP-вызовов с телом письма

Requirement: Обоснование классификации

Классификатор MUST записывать краткое обоснование решения в frontmatter (поле classification_reason), чтобы пользователь видел, почему письмо помечено именно так.

Scenario: Обоснование для письма

  • WHEN email_classifier.py классифицировал письмо
  • THEN в frontmatter записано classification_reason с 1-2 предложениями на русском

Requirement: Идемпотентность

Письмо MUST обрабатываться классификатором только один раз; повторный запуск MUST NOT переклассифицировать уже обработанные письма (если не задан флаг принудительной переклассификации).

Scenario: Повторный запуск классификатора

  • WHEN email_classifier.py запущен повторно на уже обработанном письме (есть classification)
  • THEN письмо пропускается без повторного вызова LLM

Requirement: Обработка ошибок классификатора

Если LLM не ответила или вернула невалидный JSON, классификатор MUST пометить письмо как unclassified и продолжить со следующим письмом, не прерывая весь проход.

Scenario: LLM вернула невалидный ответ

  • WHEN модель не ответила или вернула не-JSON
  • THEN письмо получает classification: unclassified, а проход продолжается