← НАЗАД К КУРСУ Этап 5 · Урок 5 из 5

Урок 5.5 — Архитектура AI-продуктов: как проектировать сложные системы

За 5 этапов курса мы изучили все кирпичики: API, промпты, агентов, инструменты, память, RAG, fine-tuning, мульти-агентные системы, оптимизацию. Каждый урок — отдельный навык. Но реальный AI-продукт — это не один кирпичик, а здание из десятков компонентов, которые должны работать вместе. Этот урок — про то, как собрать всё изученное в одну систему. Как архитектор проектирует дом до того, как положить первый кирпич — так и AI-продукт нужно спроектировать до того, как написать первую строку кода.


Зачем нужна архитектура

Можно сесть и начать писать код: вот API-вызов, вот база данных, вот Telegram-бот. Для простого проекта это работает. Но когда продукт растёт — начинаются проблемы:

Без архитектуры:
  "Добавим RAG" → воткнули в основной файл
  "Нужна память" → добавили SQLite рядом
  "Нужен второй агент" → скопировали код, поменяли промпт
  "Нужен мониторинг" → ещё один скрипт
  "Упало в продакшене" → где ошибка? В RAG? В агенте? В базе?

Через 3 месяца: 5000 строк в одном файле, всё связано со всем,
изменение в одном месте ломает три других.

Архитектура — это план системы до написания кода. Она отвечает на вопросы: - Из каких частей состоит продукт? - Как эти части общаются друг с другом? - Что произойдёт, если одна часть сломается? - Как добавить новую функцию, не сломав старые?

Аналогия

Представь, что ты строишь дом. Можно начать класть кирпичи без чертежа — и через месяц обнаружить, что забыл про канализацию, электрика не влезает в стены, а дверь выходит в стену соседа. Архитектор рисует план заранее: вот несущие стены, вот трубы, вот электропроводка. Каждый элемент на своём месте.

AI-продукт — тот же дом. API — это электричество (энергия). База данных — фундамент (хранение). Агент — жилец (логика). RAG — библиотека (знания). Архитектура — чертёж, который объединяет всё это в работающую систему.


Компоненты AI-продукта

Любой AI-продукт состоит из набора компонентов. Не все нужны в каждом проекте — но полезно знать, какие бывают:

┌──────────────────────────────────────────────────────────────┐
│                  КОМПОНЕНТЫ AI-ПРОДУКТА                       │
│                                                              │
│  ИНТЕРФЕЙС (как пользователь взаимодействует)               │
│    Telegram-бот, веб-чат, API, мобильное приложение         │
│    (урок 4.1)                                               │
│                                                              │
│  ОРКЕСТРАТОР (мозг системы)                                 │
│    Принимает запрос → решает что делать → возвращает ответ  │
│    Может быть: один агент, маршрутизатор, мульти-агент      │
│    (уроки 3.1-3.5, 5.2)                                     │
│                                                              │
│  МОДЕЛИ (AI-движки)                                         │
│    Claude, GPT, open-source модели                          │
│    Разные модели для разных задач (урок 5.4)                │
│                                                              │
│  ИНСТРУМЕНТЫ (руки агента)                                  │
│    Поиск в базе, вызов API, запись в файл, отправка email   │
│    (урок 3.2)                                               │
│                                                              │
│  ПАМЯТЬ (что система помнит)                                │
│    Краткосрочная: история чата                              │
│    Долгосрочная: база данных, факты о пользователе          │
│    (уроки 3.3, 4.2)                                         │
│                                                              │
│  ЗНАНИЯ (откуда система берёт информацию)                   │
│    RAG: векторная база с документами (урок 5.1)             │
│    Fine-tuning: навыки, вшитые в модель (урок 5.3)          │
│                                                              │
│  БЕЗОПАСНОСТЬ (защита)                                      │
│    Валидация входа, rate limiting, фильтрация вывода        │
│    (урок 4.5)                                               │
│                                                              │
│  МОНИТОРИНГ (наблюдение)                                    │
│    Логи, расходы, ошибки, качество ответов                  │
│    (урок 5.4)                                               │
│                                                              │
│  ИНФРАСТРУКТУРА (где всё работает)                          │
│    Сервер, деплой, база данных, очереди                     │
│    (уроки 4.2, 4.3)                                         │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Принцип разделения ответственности

Самый важный принцип архитектуры: каждый компонент делает одну вещь и делает её хорошо.

Плохо: один файл делает всё
  bot.py (3000 строк)
    ├── Обработка сообщений Telegram
    ├── Вызов Claude API
    ├── Поиск в RAG
    ├── Запись в базу данных
    ├── Подсчёт расходов
    ├── Валидация входа
    └── Логирование

  Проблема: чтобы изменить RAG — нужно разбираться
  в 3000 строках кода. Ошибка в подсчёте расходов
  может сломать Telegram-бота.
Хорошо: каждый файл отвечает за своё
  bot.py           → обработка сообщений (50 строк)
  orchestrator.py  → логика: что делать с запросом (100 строк)
  rag.py           → поиск по документам (80 строк)
  memory.py        → работа с базой данных (60 строк)
  llm.py           → вызовы Claude API (40 строк)
  cost_tracker.py  → подсчёт расходов (50 строк)
  security.py      → валидация и фильтрация (40 строк)

  Преимущество: нужно изменить RAG → открываешь один файл.
  Ошибка в cost_tracker → бот продолжает работать.

Аналогия

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

В AI-продукте так же: если нужно заменить Claude на GPT — меняешь только llm.py. Остальные компоненты не знают и не заботятся, какая модель внутри.


5 архитектурных паттернов

Паттерн 1: Простой бот (один агент)

Самая простая архитектура. Подходит для MVP и небольших продуктов.

┌──────────┐     ┌──────────────┐     ┌─────────┐
│ Telegram  │────▶│  Оркестратор │────▶│  Claude  │
│   бот     │◀────│  (1 агент)   │◀────│   API   │
└──────────┘     └──────┬───────┘     └─────────┘
                        │
                   ┌────▼────┐
                   │ SQLite  │
                   │ (память)│
                   └─────────┘

Когда использовать: бот отвечает на вопросы, помнит контекст, не требует поиска по документам.

Пример: персональный AI-ассистент, FAQ-бот, бот для заметок.

# Структура проекта
simple_bot/
    bot.py           # Telegram-интерфейс
    agent.py         # Оркестратор (один агент)
    memory.py        # SQLite для истории
    .env             # API-ключи
    requirements.txt
# agent.py — простой агент

from anthropic import Anthropic

client = Anthropic()

def process_message(user_id, message, history):
    """
    Принимает сообщение пользователя, возвращает ответ.
    Это единственная точка входа — бот вызывает только эту функцию.
    """
    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1024,
        system="Ты — персональный ассистент. Отвечай кратко и полезно.",
        messages=history + [{"role": "user", "content": message}]
    )
    return response.content[0].text

Паттерн 2: Бот + RAG (знания)

Добавляем поиск по документам. Бот не просто болтает — он отвечает на основе конкретных данных.

┌──────────┐     ┌──────────────┐     ┌─────────┐
│ Telegram  │────▶│  Оркестратор │────▶│  Claude  │
│   бот     │◀────│              │◀────│   API   │
└──────────┘     └──────┬───────┘     └─────────┘
                        │
                 ┌──────┴──────┐
                 │             │
            ┌────▼────┐  ┌────▼─────┐
            │ SQLite  │  │ ChromaDB │
            │ (память)│  │  (RAG)   │
            └─────────┘  └──────────┘

Когда использовать: бот должен отвечать по документации, базе знаний, FAQ компании.

Пример: бот поддержки клиентов, внутренний ассистент компании, юридический помощник.

# Структура проекта
rag_bot/
    bot.py           # Telegram-интерфейс
    orchestrator.py  # Решает: нужен RAG или обычный ответ
    rag.py           # Поиск по документам (из урока 5.1)
    memory.py        # SQLite для истории
    llm.py           # Вызовы Claude API
    load_docs.py     # Загрузка документов в ChromaDB
    my-docs/         # Папка с документами
    .env
# orchestrator.py — решает, нужен ли RAG

from rag import search_documents
from llm import ask_claude
from memory import get_history, save_message

def process_message(user_id, message):
    """
    Главная логика:
    1. Ищем релевантные документы
    2. Если нашли — отправляем с контекстом
    3. Если нет — отвечаем без контекста
    """
    history = get_history(user_id)

    # Поиск в документах
    docs = search_documents(message, n_results=3)

    if docs and docs[0]["distance"] < 1.0:
        # Нашли релевантные документы — используем RAG
        context = "\n\n".join([d["text"] for d in docs])
        answer = ask_claude(
            message=message,
            history=history,
            system=f"Отвечай на основе документов:\n\n{context}"
        )
    else:
        # Документы не найдены — обычный ответ
        answer = ask_claude(
            message=message,
            history=history,
            system="Ты — помощник компании. Если не знаешь ответ — скажи."
        )

    save_message(user_id, message, answer)
    return answer

Паттерн 3: Маршрутизатор (router)

Разные типы запросов → разные обработчики. Маленькая модель решает, куда направить запрос.

                              ┌──────────────┐
                         ┌───▶│   RAG-агент   │──▶ ChromaDB
                         │    └──────────────┘
┌──────────┐     ┌───────┴──┐
│ Telegram  │───▶│ Маршрути- │──┐ ┌──────────────┐
│   бот     │◀───│   затор   │──┼▶│  Чат-агент   │──▶ Claude
└──────────┘     │  (Haiku)  │  │ └──────────────┘
                 └───────┬──┘  │
                         │     │ ┌──────────────┐
                         └─────┴▶│ Агент задач  │──▶ Tools
                                 └──────────────┘

Когда использовать: бот выполняет разные типы задач, и для каждого типа нужна своя логика.

Пример: ассистент, который и отвечает на вопросы, и ставит напоминания, и ищет по документам.

# router.py — маршрутизатор запросов

from llm import classify, ask_claude
from rag import search_and_answer
from tasks import handle_task

def route(user_id, message):
    """
    Haiku классифицирует запрос → направляет нужному агенту.
    Стоимость классификации: ~$0.0001 (ничтожная).
    """
    # Шаг 1: Haiku определяет тип запроса
    intent = classify(message)
    # Возвращает: "question", "task", "chat"

    # Шаг 2: Направляем нужному обработчику
    if intent == "question":
        # Вопрос по документам → RAG
        return search_and_answer(message)

    elif intent == "task":
        # Задача: напоминание, расчёт, действие → агент с инструментами
        return handle_task(user_id, message)

    else:
        # Обычный разговор → чат-агент
        return ask_claude(message)
# llm.py — обёртка над Claude API

from anthropic import Anthropic

client = Anthropic()

def classify(message):
    """Haiku классифицирует тип запроса. Дёшево и быстро."""
    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=20,
        messages=[{
            "role": "user",
            "content": f"""Классифицируй запрос. Ответь одним словом:
question — вопрос, требующий поиска информации
task — задача, действие, напоминание
chat — обычный разговор

Запрос: {message}"""
        }]
    )
    return response.content[0].text.strip().lower()


def ask_claude(message, history=None, system=None, model="claude-sonnet-4-6"):
    """Универсальная обёртка для вызова Claude."""
    messages = (history or []) + [{"role": "user", "content": message}]

    response = client.messages.create(
        model=model,
        max_tokens=1024,
        system=system or "Ты — полезный ассистент.",
        messages=messages
    )
    return response.content[0].text

Паттерн 4: Конвейер (pipeline)

Запрос проходит через цепочку шагов. Каждый шаг — отдельный компонент.

Запрос ──▶ Валидация ──▶ Обогащение ──▶ Генерация ──▶ Проверка ──▶ Ответ
           (security)    (RAG/память)    (Claude)      (фильтр)

Когда использовать: каждый запрос должен пройти фиксированные этапы обработки.

Пример: бот поддержки с проверкой безопасности, поиском контекста и фильтрацией ответа.

# pipeline.py — конвейер обработки запроса

from security import validate_input, filter_output
from rag import find_context
from memory import get_history, save_message
from llm import ask_claude
from cost_tracker import log_cost

def process(user_id, message):
    """
    Конвейер: запрос проходит 5 шагов последовательно.
    Если шаг падает — возвращаем безопасный ответ.
    """

    # Шаг 1: Валидация (безопасность)
    is_safe, reason = validate_input(message)
    if not is_safe:
        return f"Не могу обработать этот запрос: {reason}"

    # Шаг 2: Обогащение (собираем контекст)
    history = get_history(user_id, limit=10)
    context = find_context(message)  # RAG-поиск

    # Шаг 3: Генерация (вызов модели)
    system = "Ты — помощник техподдержки."
    if context:
        system += f"\n\nКонтекст из документов:\n{context}"

    answer = ask_claude(message, history=history, system=system)

    # Шаг 4: Фильтрация вывода (безопасность)
    answer = filter_output(answer)

    # Шаг 5: Сохранение и логирование
    save_message(user_id, message, answer)

    return answer

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


Паттерн 5: Мульти-агентная система

Несколько специализированных агентов под управлением оркестратора. Самый сложный, но самый мощный паттерн.

                         ┌──────────────────────┐
                         │     ОРКЕСТРАТОР       │
                         │ (планирует, делегирует)│
                         └──┬────────┬────────┬──┘
                            │        │        │
                   ┌────────▼─┐  ┌───▼────┐  ┌▼─────────┐
                   │ RAG-агент│  │Аналитик│  │ Писатель  │
                   │(документы)│  │(данные)│  │ (тексты)  │
                   └────┬─────┘  └───┬────┘  └─────┬─────┘
                        │            │             │
                   ┌────▼────┐  ┌───▼────┐       Claude
                   │ChromaDB │  │  SQL   │
                   └─────────┘  └────────┘

Когда использовать: задача требует разных навыков, контекст одного агента переполняется, подзадачи можно выполнять параллельно.

Пример: AI-аналитик, который ищет данные, анализирует их и пишет отчёт. Подробно разобрано в уроке 5.2.


Какой паттерн выбрать

Что строишь?
│
├── Простой чат-бот, FAQ
│   → Паттерн 1: Простой бот
│   → Один файл agent.py + память
│
├── Бот с доступом к документам
│   → Паттерн 2: Бот + RAG
│   → orchestrator + rag + memory
│
├── Бот с разными типами задач
│   → Паттерн 3: Маршрутизатор
│   → router + специализированные обработчики
│
├── Продакшн-бот с безопасностью и мониторингом
│   → Паттерн 4: Конвейер
│   → pipeline с шагами: валидация → контекст → генерация → фильтр
│
└── Сложная система с несколькими AI-специалистами
    → Паттерн 5: Мульти-агент
    → orchestrator + агенты (урок 5.2)

Принцип: начинай с Паттерна 1. Усложняй только когда простое не работает. Тот же принцип, что и для всего остального в курсе.


Структура проекта: как организовать файлы

Маленький проект (Паттерн 1-2)

my-bot/
├── bot.py              # Telegram-интерфейс
├── agent.py            # Логика агента
├── memory.py           # Работа с SQLite
├── .env                # API-ключи (НЕ в git!)
├── .gitignore          # Исключения для git
├── requirements.txt    # Зависимости (pip freeze)
└── README.md           # Как запустить

Средний проект (Паттерн 3-4)

support-bot/
├── bot.py              # Telegram-интерфейс
├── router.py           # Маршрутизатор запросов
├── agents/
│   ├── chat.py         # Чат-агент
│   ├── rag.py          # RAG-агент
│   └── tasks.py        # Агент задач
├── core/
│   ├── llm.py          # Обёртка Claude API
│   ├── memory.py       # Работа с SQLite
│   └── security.py     # Валидация и фильтрация
├── data/
│   ├── docs/           # Документы для RAG
│   └── chroma_db/      # Векторная база
├── monitoring/
│   ├── cost_tracker.py # Подсчёт расходов
│   └── logger.py       # Логирование
├── .env
├── .gitignore
├── requirements.txt
└── README.md

Почему именно так

bot.py — точка входа. Знает только про router.
  Не знает про Claude, RAG или базу данных.

router.py — принимает решения. Знает про агентов.
  Не знает, как агенты устроены внутри.

agents/ — каждый агент в своём файле. Знает про llm.py.
  Не знает про Telegram или другие агенты.

core/ — общие компоненты. llm.py, memory.py, security.py.
  Не знают, кто их вызывает.

monitoring/ — наблюдение. Можно удалить — система работает.
  Но без мониторинга не видно проблем.

Каждый уровень знает только про уровень ниже. Telegram не знает про Claude. Claude не знает про Telegram. Связывает их оркестратор.


Обработка ошибок: что может пойти не так

В реальном продукте всё ломается. API не отвечает, база данных падает, пользователь отправляет мусор. Архитектура должна это учитывать.

Что ломается и что делать

Проблема 1: Claude API не отвечает (таймаут, 500 ошибка)
  Решение: retry с задержкой + fallback
  → Попробовать ещё раз через 2 секунды
  → Если 3 попытки не помогли — ответить заготовкой:
    "Извините, сейчас не могу ответить. Попробуйте позже."

Проблема 2: RAG не находит документы
  Решение: fallback на обычный ответ
  → "В документах не нашёл ответа, но вот что я думаю..."
  → Или: "Не нашёл информацию. Обратитесь в поддержку: ..."

Проблема 3: Пользователь отправляет prompt injection
  Решение: валидация входа (урок 4.5)
  → Проверять сообщение ДО отправки в Claude
  → Фильтровать вывод ПОСЛЕ получения ответа

Проблема 4: Превышен бюджет на API
  Решение: лимиты (урок 5.4)
  → Дневной лимит: $5
  → Лимит на пользователя: 50 запросов/день
  → Если лимит исчерпан: "Лимит запросов на сегодня достигнут."

Проблема 5: Модель галлюцинирует (выдаёт ложную информацию)
  Решение: RAG + проверка
  → Отвечать ТОЛЬКО на основе документов
  → Системный промпт: "Если информации нет — скажи, что не знаешь."
  → Для критических задач: человек проверяет ответ перед отправкой

Код: retry с fallback

# llm.py — вызов Claude с обработкой ошибок

import time
from anthropic import Anthropic, APIError, APITimeoutError

client = Anthropic()

def ask_claude(message, system=None, model="claude-sonnet-4-6", max_retries=3):
    """
    Вызов Claude с автоматическим повтором при ошибках.
    Если все попытки провалились — возвращает fallback-ответ.
    """
    for attempt in range(max_retries):
        try:
            response = client.messages.create(
                model=model,
                max_tokens=1024,
                system=system or "Ты — полезный ассистент.",
                messages=[{"role": "user", "content": message}]
            )
            return response.content[0].text

        except APITimeoutError:
            # API не ответил вовремя — ждём и пробуем снова
            if attempt < max_retries - 1:
                wait = 2 ** attempt  # 1с, 2с, 4с (экспоненциальная задержка)
                time.sleep(wait)
            else:
                return "Извините, сервис временно недоступен. Попробуйте позже."

        except APIError as e:
            # Ошибка API (429 = слишком много запросов, 500 = сервер упал)
            if e.status_code == 429:
                time.sleep(5)  # rate limit — ждём подольше
            elif attempt == max_retries - 1:
                return "Произошла ошибка. Попробуйте позже."

Экспоненциальная задержка (exponential backoff)

Вместо того чтобы бомбить API повторными запросами — каждый следующий повтор ждёт дольше:

Попытка 1: ошибка → ждём 1 секунду
Попытка 2: ошибка → ждём 2 секунды
Попытка 3: ошибка → ждём 4 секунды
Попытка 4: все попытки исчерпаны → возвращаем fallback

Аналогия. Звонишь другу — занято. Перезваниваешь через минуту — занято. Через 5 минут — занято. Через 15 минут — не берёт. Не звонишь каждые 2 секунды — это раздражает и не помогает.


Масштабирование: когда пользователей становится много

Проблемы роста

10 пользователей:   всё работает, SQLite хватает
100 пользователей:  всё ещё нормально
1000 пользователей: SQLite начинает тормозить, API-счёт растёт
10 000:             нужна очередь, кеширование, мониторинг

Решения по этапам

Этап 1: до 100 пользователей (MVP)
  ├── SQLite для памяти
  ├── ChromaDB для RAG
  ├── Один сервер
  └── Haiku для простых задач

Этап 2: 100-1000 пользователей
  ├── PostgreSQL вместо SQLite (надёжнее при параллельных запросах)
  ├── Prompt caching (экономия 90%)
  ├── Маршрутизатор моделей (Haiku/Sonnet)
  └── Логирование расходов

Этап 3: 1000-10 000 пользователей
  ├── Очередь задач (Redis + Celery или аналог)
  │   Запросы складываются в очередь, обрабатываются по порядку.
  │   Пользователь не ждёт — получает "Обрабатываю..." и потом ответ.
  ├── Кеширование ответов
  │   Одинаковые вопросы → одинаковый ответ из кеша (без вызова API).
  ├── Batch API для фоновых задач
  └── Мониторинг (Grafana, Prometheus или простые логи)

Кеширование ответов

Если 100 пользователей в день спрашивают «Как оформить возврат?» — зачем вызывать Claude 100 раз?

# cache.py — простой кеш ответов

import json
import hashlib
import time

CACHE_FILE = "response_cache.json"
CACHE_TTL = 3600  # 1 час (секунды)

def get_cache_key(message):
    """Создаёт уникальный ключ из текста сообщения."""
    return hashlib.md5(message.lower().strip().encode()).hexdigest()
    # md5 превращает любой текст в уникальную строку из 32 символов
    # "Как оформить возврат?" → "a1b2c3d4e5f6..."

def get_cached(message):
    """Ищет ответ в кеше. Возвращает None, если не найден или устарел."""
    key = get_cache_key(message)

    try:
        with open(CACHE_FILE) as f:
            cache = json.load(f)
    except (FileNotFoundError, json.JSONDecodeError):
        return None

    entry = cache.get(key)
    if entry and time.time() - entry["timestamp"] < CACHE_TTL:
        return entry["response"]  # Нашли! Возвращаем без вызова API
    return None

def save_to_cache(message, response):
    """Сохраняет ответ в кеш."""
    key = get_cache_key(message)

    try:
        with open(CACHE_FILE) as f:
            cache = json.load(f)
    except (FileNotFoundError, json.JSONDecodeError):
        cache = {}

    cache[key] = {"response": response, "timestamp": time.time()}

    with open(CACHE_FILE, "w") as f:
        json.dump(cache, f)


# Использование в оркестраторе:
def process(message):
    # Сначала проверяем кеш
    cached = get_cached(message)
    if cached:
        return cached  # Бесплатно!

    # Кеша нет — вызываем Claude
    answer = ask_claude(message)

    # Сохраняем в кеш для следующих
    save_to_cache(message, answer)
    return answer

Реальные архитектуры AI-продуктов

Бот поддержки клиентов

┌──────────────────────────────────────────────────────────────┐
│                 БОТ ПОДДЕРЖКИ КЛИЕНТОВ                        │
│                                                              │
│  Пользователь                                               │
│       │                                                      │
│       ▼                                                      │
│  [Telegram / Веб-чат / WhatsApp]                            │
│       │                                                      │
│       ▼                                                      │
│  ┌─────────────┐                                            │
│  │  Валидация   │ ← Проверка на prompt injection            │
│  └──────┬──────┘                                            │
│         ▼                                                    │
│  ┌─────────────┐     ┌──────────────┐                       │
│  │ Маршрутизатор│────▶│ Определение  │                       │
│  │   (Haiku)    │     │ категории    │                       │
│  └──────┬──────┘     └──────────────┘                       │
│         │                                                    │
│    ┌────┼────┐                                              │
│    ▼    ▼    ▼                                              │
│  [FAQ] [Заказ] [Жалоба]                                    │
│    │     │       │                                          │
│    ▼     ▼       ▼                                          │
│  RAG   API      Sonnet ── "Эскалация: передаю человеку"    │
│  │    магазина     │                                        │
│  ▼     │          ▼                                         │
│  Haiku ▼       Запись в                                     │
│    │  Haiku    CRM                                          │
│    │   │                                                     │
│    ▼   ▼                                                     │
│  ┌───────────┐                                              │
│  │  Фильтр   │ ← Убираем PII, проверяем корректность       │
│  └─────┬─────┘                                              │
│        ▼                                                     │
│  [Ответ пользователю]                                       │
│                                                              │
│  + Мониторинг: расходы, время ответа, удовлетворённость     │
│  + Память: SQLite (история), ChromaDB (документы)           │
└──────────────────────────────────────────────────────────────┘

AI-ассистент для аналитики

┌──────────────────────────────────────────────────────────────┐
│              AI-АССИСТЕНТ ДЛЯ АНАЛИТИКИ                       │
│                                                              │
│  "Покажи продажи за прошлый месяц по категориям"            │
│       │                                                      │
│       ▼                                                      │
│  ┌──────────────────┐                                       │
│  │    Оркестратор    │  (Sonnet — понимает задачу)           │
│  │  "Нужно: данные   │                                       │
│  │   + анализ        │                                       │
│  │   + визуализация" │                                       │
│  └────┬─────┬────────┘                                      │
│       │     │                                                │
│  ┌────▼──┐ ┌▼──────────┐                                    │
│  │SQL-   │ │ Аналитик  │                                    │
│  │агент  │ │           │                                    │
│  │(Haiku)│ │ (Sonnet)  │                                    │
│  └───┬───┘ └─────┬─────┘                                    │
│      │           │                                           │
│      ▼           ▼                                           │
│  PostgreSQL   "Продажи выросли                              │
│  → таблица     на 15%..."                                   │
│    данных       │                                            │
│      │          ▼                                            │
│      └──▶ ┌──────────┐                                      │
│           │ Генератор │                                      │
│           │  отчёта   │                                      │
│           └─────┬────┘                                      │
│                 ▼                                             │
│           [Отчёт с графиком                                  │
│            в Telegram]                                       │
└──────────────────────────────────────────────────────────────┘

Чек-лист: перед запуском AI-продукта

Перед тем как показать продукт пользователям — проверь:

ФУНКЦИОНАЛЬНОСТЬ
  □ Бот отвечает на типовые вопросы корректно
  □ Бот говорит "не знаю", когда не знает (а не выдумывает)
  □ История чата сохраняется между сессиями
  □ RAG находит релевантные документы (если используется)

БЕЗОПАСНОСТЬ (урок 4.5)
  □ API-ключи в .env, не в коде
  □ .env добавлен в .gitignore
  □ Есть защита от prompt injection
  □ Вывод фильтруется (нет PII, нет вредного контента)
  □ Rate limiting: ограничение запросов на пользователя

СТОИМОСТЬ (урок 5.4)
  □ Правильная модель для каждой задачи (не Opus для FAQ)
  □ Prompt caching включен (если повторяющийся контекст)
  □ max_tokens ограничен (не 4096 для простого ответа)
  □ Дневной бюджет установлен
  □ Расходы логируются

НАДЁЖНОСТЬ
  □ Ошибки API обрабатываются (retry + fallback)
  □ Если база недоступна — бот не падает
  □ Если бюджет исчерпан — пользователь получает сообщение
  □ Логи записываются для отладки

ДЕПЛОЙ (урок 4.3)
  □ Бот работает на сервере (не на ноутбуке)
  □ systemd перезапускает при падении
  □ Есть способ обновить код без потери данных

Практика

Задание 1: Спроектируй архитектуру

Выбери AI-продукт (можно свой или из списка): - Бот-ассистент для интернет-магазина - AI-помощник для изучения английского - Бот, который анализирует расходы из чеков

Нарисуй схему архитектуры: какие компоненты, как связаны, какие модели используешь. Используй ASCII-диаграммы как в этом уроке.

Задание 2: Реализуй конвейер

Возьми бота из урока 4.1 и преврати его в конвейер (Паттерн 4): 1. Вынеси логику в отдельные файлы: llm.py, memory.py, security.py 2. Добавь pipeline.py с шагами: валидация → контекст → генерация → фильтр 3. Добавь cost_tracker.py из урока 5.4

Задание 3: Добавь кеширование

Добавь кеш ответов из этого урока. Проверь: если два пользователя задают одинаковый вопрос — второй получает ответ мгновенно (без вызова API). Подсчитай, сколько API-вызовов экономит кеш за день.


Задачки на закрепление

Задача 1: Зачем разделять код на отдельные файлы?

Ответ Разделение ответственности: каждый файл отвечает за одну задачу. Если нужно изменить RAG — открываешь один файл, не трогая остальные. Если ошибка в подсчёте расходов — бот продолжает работать. Если нужно заменить Claude на GPT — меняешь только llm.py. Код проще читать, тестировать и поддерживать.

Задача 2: Когда использовать маршрутизатор, а когда конвейер?

Ответ Маршрутизатор (router) — когда разные типы запросов требуют РАЗНОЙ обработки. Вопрос → RAG, задача → агент, болтовня → чат. Запрос идёт по одному из путей. Конвейер (pipeline) — когда КАЖДЫЙ запрос проходит одни и те же шаги: валидация → контекст → генерация → фильтр. Можно комбинировать: конвейер внутри каждой ветки маршрутизатора.

Задача 3: Почему exponential backoff лучше, чем повторять запрос сразу?

Ответ Если API перегружен (ошибка 429 или 500) и ты повторяешь запрос мгновенно — ты добавляешь нагрузку на и без того перегруженный сервер. Это как толпа, которая давит на закрытую дверь — от давления дверь не откроется быстрее. Экспоненциальная задержка (1с → 2с → 4с) даёт серверу время восстановиться. К тому же провайдеры могут заблокировать клиента, который бомбит повторными запросами.

Задача 4: У тебя 1000 пользователей в день задают одни и те же 50 вопросов. Какие стратегии применить?

Ответ 1. Кеширование ответов — 50 уникальных вопросов = 50 вызовов API вместо 1000. Экономия 95%. 2. RAG с документами FAQ — ответы точные, на основе документов. 3. Haiku вместо Sonnet — для FAQ хватает дешёвой модели. 4. Prompt caching — системный промпт кешируется между запросами. Комбинация: кеш ответов + Haiku + prompt caching = стоимость близка к нулю.

Задача 5: Что должен делать бот, если Claude API не отвечает?

Ответ 1. Retry с экспоненциальной задержкой (1с, 2с, 4с). 2. Если все попытки провалились — вернуть fallback-ответ: «Извините, сервис временно недоступен. Попробуйте через несколько минут.» 3. Записать ошибку в лог для отладки. 4. НЕ показывать пользователю техническую ошибку (stack trace). Бот никогда не должен «молча умирать» — пользователь всегда получает ответ, даже если это сообщение об ошибке.

Глоссарий

Термин Что значит
Архитектура План системы: из каких частей состоит, как они связаны, как взаимодействуют
Компонент Отдельная часть системы с одной ответственностью (бот, агент, память, RAG)
Разделение ответственности Принцип: каждый компонент делает одну вещь. Изменение одного не ломает другие
Оркестратор Центральный компонент, который принимает запрос и решает, что с ним делать
Маршрутизатор (router) Компонент, который направляет запрос нужному обработчику по типу задачи
Конвейер (pipeline) Последовательность шагов, через которые проходит каждый запрос
Fallback Запасной ответ, когда основная логика сломалась (API не отвечает, база упала)
Retry Повторная попытка запроса после ошибки
Exponential backoff Стратегия повтора с увеличивающейся задержкой: 1с → 2с → 4с → 8с
Rate limiting Ограничение количества запросов на пользователя за период времени
Кеширование ответов Сохранение ответов на частые вопросы, чтобы не вызывать API повторно
TTL (Time to Live) Время жизни записи в кеше. После TTL запись считается устаревшей
MVP Minimum Viable Product — минимальный работающий продукт для проверки идеи
Масштабирование Способность системы работать с растущим количеством пользователей
Очередь задач Механизм (Redis, Celery), где запросы складываются в очередь и обрабатываются по порядку
Эскалация Передача сложного запроса от бота живому оператору

Главное

Архитектура = план системы до написания кода

Главный принцип:
  Каждый компонент делает одну вещь.
  bot.py не знает про Claude. llm.py не знает про Telegram.

5 паттернов (от простого к сложному):
  1. Простой бот — один агент + память
  2. Бот + RAG — агент + поиск по документам
  3. Маршрутизатор — разные запросы → разные обработчики
  4. Конвейер — валидация → контекст → генерация → фильтр
  5. Мульти-агент — оркестратор + специализированные агенты

Обработка ошибок:
  • Retry с exponential backoff (1с → 2с → 4с)
  • Fallback-ответ, если всё сломалось
  • Лимиты бюджета и rate limiting
  • Логирование для отладки

Масштабирование:
  10 пользователей → SQLite, один сервер
  1000 → PostgreSQL, prompt caching, маршрутизатор
  10 000 → очередь, кеш ответов, batch API

Начинай с Паттерна 1. Усложняй только когда простое не работает.

Что дальше?

Это последний урок курса AI Academy. За 5 этапов пройден путь от «что такое терминал» до проектирования архитектуры AI-продуктов. Вот карта того, что теперь доступно:

┌──────────────────────────────────────────────────────────────┐
│                    ТВОЙ НАБОР НАВЫКОВ                          │
│                                                              │
│  Фундамент:      терминал, Python, Git, файлы               │
│  Понимание AI:    LLM, API, промпты, токены, стоимость       │
│  Агенты:          tools, память, Agent SDK, мульти-шаг       │
│  Продукты:        Telegram-бот, БД, деплой, безопасность     │
│  Экспертный:      RAG, мульти-агенты, fine-tuning,           │
│                   оптимизация, архитектура                    │
│                                                              │
│  Этого достаточно, чтобы:                                    │
│    → Создать AI-продукт с нуля                              │
│    → Задеплоить его на сервер                                │
│    → Сделать его безопасным и экономичным                    │
│    → Масштабировать на тысячи пользователей                  │
│    → Понимать архитектуру любого AI-продукта на рынке        │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Дальше — практика. Лучший способ закрепить знания — построить свой продукт. Взять идею, спроектировать архитектуру, написать код, задеплоить и показать людям. Всё, что для этого нужно — в этом курсе.

← ПРЕДЫДУЩИЙ СЛЕДУЮЩИЙ →