mirror of
https://gitverse.ru/kpa39l/email-assistant.git
synced 2026-09-29 21:25:10 +00:00
Задача 8: классификация и обработчики — живой прогон, cron, archive change
This commit is contained in:
+57
@@ -0,0 +1,57 @@
|
||||
## Purpose
|
||||
|
||||
Классификация писем локальной LLM: после скачивания письма модель определяет тип
|
||||
письма (информационное, требует срочного ответа, содержит задачу, содержит
|
||||
встречу) и записывает тег + обоснование в frontmatter файла email.md. Обработка
|
||||
приватна — модель Qwen3:8b запущена локально через Ollama, текст письма не
|
||||
покидает хост.
|
||||
|
||||
## ADDED 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`, а проход продолжается
|
||||
Reference in New Issue
Block a user