Автоматизация фотоархива и очистка почты с AI-агентами и локальными моделями | AiManual
AiManual Logo Ai / Manual.
14 Июн 2026 Гайд

Ваши 36 000 фото и 20 лет почты: как не умереть от хаоса с локальным AI-агентом

Полное руководство: как с помощью LLaVA, Ollama, Gmail API и Python разобрать 36 000 фото и очистить 20-летний почтовый ящик. Без облаков и потери данных.

Реклама
cliv1

Представьте: на жёстком диске 36 000 фотографий. Перемешаны: скриншоты, чеки, еда, котики, фото паспорта, мемы из 2010-го. В Gmail — 20 лет переписки: 15 тысяч рассылок, спам, уведомления от древних форумов, письма от бывших работодателей. Руками разгребать — год. Нанимать виртуального ассистента — дорого и небезопасно. Облачный AI — спасибо, но я свои данные в чужие GPU не отправляю.

Встречайте решение: локальный AI-агент, который сам сортирует фотки, чистит почту и не просит доступ к интернету. В этой статье я расскажу, как собрать такого агента из Ollama, LLaVA, Gmail API и пары скриптов на Python. Спойлер: это работает, но есть подводные камни, на которых я набил шишки. Поехали.

Проблема: 36 000 файлов и 20 лет почты — это не просто цифры

Когда я впервые посмотрел на содержимое своего фотоархива, мне стало физически плохо. 36 000 файлов — это не просто "много". Это полный хаос:

  • Фотографии с телефона — последние 10 лет, но без альбомов.
  • Скриншоты экранов — от билетов до ошибок кода.
  • Фото документов — паспорт, права, договоры — все в одной куче.
  • Десятки гигабайт дублей и похожих изображений.

С почтой та же история. Мой основной Gmail (зарегистрирован в 2006-м) дорос до 18 ГБ писем. Из них реально нужных — может, 100 штук. Остальное — рассылки, подтверждения регистраций, уведомления от сервисов, которые уже 10 лет как закрылись. Удалять руками — бессмысленно. Фильтры Gmail — примитивны.

Железобетонное правило: Не трогайте оригиналы, пока не сделаете бекап. У меня на внешнем диске лежит raw-копия всех файлов. Если AI что-то напутает — я не потеряю данные.

Решение: AI-агент на локальных моделях. Почему не облако?

Облачные сервисы (Google Photos, Dropbox AI) хороши, но есть нюанс: они видят все ваши фотки и письма. Я не параноик, но когда AI начинает описывать содержимое личных фото — мне это не нравится. К тому же заливать 36 000 файлов в облако — дохлый номер по времени и трафику.

Локальные модели решают обе проблемы: данные никуда не уходят, скорость ограничена только вашим железом. Мы используем Ollama (платформа для запуска LLM инференса), LLaVA (мультимодальная модель для анализа изображений) и Python для склеивания всего в единый пайплайн.

Кстати, если у вас слабая видеокарта или вообще только CPU — не беда. Я покажу, как адаптировать решение под $20-сервер. А если хотите полноценный AI-агент прямо на смартфоне — вот вам статья про A.I.R.I: превращаем Android в локальный AI-сервер — там как раз описан похожий подход.

Архитектура: как заставить AI-агента не ломаться на половине

Мой агент состоит из трёх модулей:

  1. Сборщик данных — проходит по файловой системе, собирает метаданные (EXIF, даты, размеры). Для почты — дергает Gmail API.
  2. Анализатор — отправляет каждый файл (или сэмпл) в локальную модель для описания и категоризации.
  3. Исполнитель — на основе анализа сортирует файлы в папки, удаляет дубли, помечает письма для архивации или удаления.

База — Ollama с моделями LLaVA 1.6 (7B) для фото и Qwen2.5 (7B) для текста писем. На моём ноутбуке с RTX 4060 (6 ГБ VRAM) одна обработка фото занимает ~1.5 секунды. Для 36 000 фото это ~15 часов непрерывной работы. Звучит долго, но это в 100 раз быстрее, чем делать руками.

Почему не ChatGPT API? Во-первых, цена: 36 000 запросов к GPT-4o — это $200-300. Во-вторых, конфиденциальность. В-третьих, скорость: локальная модель выдаёт ответ за 0.5-2 сек на моём GPU. API может тормозить из-за очереди.

Кстати, если вас интересует, как организовать бесконечную очередь задач и не уронить сервер — почитайте статью про RAG для 4 миллионов PDF. Там описана архитектура очередей, которая идеально ложится на наш сценарий.

Шаг 1: Сортировка фото — как не перепутать кота с кредиткой

1 Установка Ollama и запуск LLaVA

Устанавливаем Ollama любой версии (я на 0.5.0, но свежие работают так же):

curl -fsSL https://ollama.com/install.sh | sh
ollama pull llava:7b  # последняя на 14.06.2026 версия 1.6
ollama run llava:7b

Проверяем, что модель отвечает. Теперь пишем скрипт-агент, который будет обходить папку с фото, отбирать кадры (не все 36 000 сразу) и отправлять в модель с промптом:

import os
import json
import subprocess
from PIL import Image
import concurrent.futures

def analyze_image(image_path):
    prompt = "Опиши, что на фотографии. Ответь одним словом или короткой фразой: 'еда', 'документ', 'скриншот', 'пейзаж', 'портрет', 'животное', 'город', 'интерьер', 'прочее'. "
    # Используем ollama через subprocess (или библиотеку)
    result = subprocess.run(
        ['ollama', 'run', 'llava:7b', prompt],
        input=image_path,
        capture_output=True,
        text=True
    )
    return result.stdout.strip()

# Пример с пулом потоков
paths = [...]  # список файлов
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
    results = list(executor.map(analyze_image, paths))

Этот код — каркас. На практике я добавил извлечение EXIF, хэши для поиска дублей и буферизацию результатов. Без буфера вы рискуете, что при сбое (а они будут) придётся перезапускать с нуля. Я сохраняю промежуточные результаты в SQLite.

2 Категоризация и переименование

LLaVA часто ошибается. Например, фото паспорта может определить как "документ" (хорошо), а еду — как "натюрморт" (не очень). Чтобы повысить точность, я использую Chain-of-Thought промпт:

prompt = """Ты классификатор фотографий. Вот изображение. Определи категорию из списка: документ, еда, животное, портрет, пейзаж, скриншот, интерьер, город, прочее. Ответь только названием категории.
Если на фото есть лицо человека, это 'портрет' (даже если это селфи с едой). Если виден экран — 'скриншот'. Если расплывчато — 'прочее'."""

После категоризации я сортирую файлы по папкам вида /Фото/2024/2024-06-скриншоты. Даты беру из EXIF, если нет — из времени создания файла. Помогает избежать путаницы.

Грабли, на которые я наступил: LLaVA иногда выдаёт категорию на другом языке (например, "food" вместо "еда"). Нормализуйте ответы. Я добавил маппинг: food→еда, screenshot→скриншот. И всегда проверяйте, что ответ входит в допустимый список. Иначе — "прочее".

Если хотите готовое решение, посмотрите AI File Sorter 1.5 — как раз про локальную сортировку и переименование тысяч фото с помощью LLaVA.

Шаг 2: Очистка почты — AI-агент против 20 лет спама

Тут задача сложнее. Письма — не картинки, их надо читать и понимать контекст. Gmail API позволяет вытащить все письма, но лимиты: 10 запросов в секунду на пользователя. Для 20 тысяч писем это ~30 минут только на получение.

Мой подход: сначала агент собирает только метаданные (от кого, тема, дата) — они доступны без полного текста. Затем классифицирует письма локальной моделью. Если письмо подозрительное (спам, рассылка) — удаляет без открытия. Если важное — помечает звёздочкой.

3 Получение писем через Gmail API

import google.auth
from googleapiclient.discovery import build

creds, _ = google.auth.default()
service = build('gmail', 'v1', credentials=creds)

# Получить список всех писем
results = service.users().messages().list(userId='me', maxResults=500).execute()
messages = results.get('messages', [])
while 'nextPageToken' in results:
    page_token = results['nextPageToken']
    results = service.users().messages().list(
        userId='me', maxResults=500, pageToken=page_token).execute()
    messages.extend(results.get('messages', []))

# Для каждого письма получаем ID и тему (через snippet/metadata)
for msg in messages:
    meta = service.users().messages().get(
        userId='me', id=msg['id'], format='metadata',
        metadataHeaders=['From', 'Subject']).execute()
    headers = meta['payload']['headers']
    subject = next(h['value'] for h in headers if h['name'] == 'Subject')
    sender = next(h['value'] for h in headers if h['name'] == 'From')
    # Отправляем в модель для анализа

Внимание: никогда не удаляйте письма сразу! Сначала переместите их в папку "на удаление" (пометьте меткой). Я создал метку "Удалить_через_30_дней". Через месяц проверяю, что ничего важного не потеряно, и только тогда удаляю окончательно.

4 Классификация писем локальной LLM

Для текста я использую Qwen2.5 7B (она лучше понимает русский и не требует мощного GPU). Промпт:

prompt = f"""Классифицируй письмо:
От: {sender}
Тема: {subject}

Варианты: 
- 'спам/реклама' - если это незапрашиваемая реклама или спам
- 'рассылка' - если это подписка, уведомление, рассылка
- 'важное' - если письмо от человека или требует ответа
- 'транзакция' - если это чек, подтверждение заказа, квитанция
- 'прочее' - если не подходит ни под одну

Ответь только одним словом."""

Модель работает стабильно. Ошибки бывают: иногда важное письмо от банка помечает как "рассылка" — это решается добавлением белого списка отправителей. В целом точность ~92% на моём датасете.

Подводные камни: что пошло не так и как чинить

Не буду врать, что всё прошло гладко. Вот типичные проблемы:

  • Лимиты Gmail API. Даже при 500 запросах в минуту, если запустить обход сразу всех писем, Google может временно заблокировать аккаунт. Решение: ввести задержку между запросами time.sleep(0.1) и использовать экспоненциальный backoff.
  • Зависание модели. LLaVA иногда вешает ответ — бесконечно генерирует токены. Ставьте таймаут на запрос (я ставлю 30 секунд). Если превышен — считаем, что ошибка, и пропускаем файл.
  • Нехватка VRAM. Если запускать две модели одновременно (фото и текст), 6 ГБ может не хватить. Решение: поставить очередь задач — сначала обработать все фото, потом письма. Или использовать CPU-версию для текстовой модели (медленно, но надёжно).
  • Контекстная слепота. Агент видит только одно фото или одно письмо за раз, но не учитывает общий контекст всей коллекции. Как с этим бороться — описано в статье про контекстную слепоту агентов. Я добавил базу данных, где фиксирую историю решений, и модель иногда запрашивает похожие случаи.

Ещё один грабль — дубли в фото. Одно и то же фото может лежать в разных папках или с разным именем. LLaVA их не распознаёт. Для сравнения я использую средний хеш (pHash) — это отсекает 99% дублей. Если хотите готовую утилиту, Immich из коробки умеет находить дубли — гляньте Makimus-AI: ваш личный Google Photos, который не шпионит.

Результаты: что получилось после месяца работы

После прогона через мой AI-агент:

  • Фото: 36 000 файлов отсортированы по годам и категориям. Удалены 4 000 дублей. Найдено 200 фото документов (раньше я искал их неделями).
  • Почта: из 18 000 писем удалено 12 000 (спам и рассылки). Оставлено 6 000 важных и транзакционных. Ручная проверка показала, что случайно удалено всего ~50 писем (восстановил из корзины).
  • Затраты: $0 — всё локально. Электроэнергия: ~500 рублей. Время: ~20 часов процессорного времени, из них 90% — работа модели.

Я остался доволен, но без боли не обошлось. Если вы решите повторить, начните с малого: возьмите 100 фото и 10 писем. Доведите пайплайн до ума, а только потом запускайте на полном датасете. И обязательно логируйте всё — иначе никогда не поймёте, почему агент решил удалить важный контракт.

Что дальше? Агент-оркестратор и база знаний

Сейчас я развиваю эту идею: хочу, чтобы агент не просто сортировал, а умел отвечать на вопросы по содержимому архива. Например, "Покажи все счета за электричество за 2023 год". Для этого нужна база знаний, в которую модель будет индексировать все документы и письма. Как построить такую базу — отлично расписано в руководстве по построению эффективной базы знаний для AI-моделей.

Если у вас много документов (чеки, договоры, PDF) — рекомендую изучить обработку 4700 инженерных PDF за 45 минут — системный дизайн там пригодится. А для распознавания текста на фото документов — гайд от OCR к ADE.

И не забывайте: AI-агент — это инструмент. Он тупой, как пробка, и делает только то, что вы ему скажете. Поэтому сначала опишите чёткие правила, потом внедряйте. Удачи, и пусть ваш архив будет в порядке.

Бонус-совет: не гонитесь за точностью 100%. Лучше пусть агент пересортирует 5% фото не туда, чем вы будете тратить недели на ручную классификацию. Исправляйте категории на лету, когда найдёте ошибку — добавляйте пример в few-shot промпт. Через 1000 итераций модель станет заметно точнее.

Подписаться на канал