- BrainTools - https://www.braintools.ru -

Делюсь опытом: ИИ-агент на Claude без LangChain и RAG — разбор архитектуры и развилок

Зачем я это пишу

Запустил недавно прод-агента на Claude — небольшой, для бытовой задачи у знакомой. По дороге понял несколько вещей, которые сначала казались мне очевидными «после интернета», а потом, когда сел и проверил на реальной задаче, начали играть иначе. Хочется поделиться разбором — может, кому-то сэкономит неделю-другую на тех же развилках.

Сразу честно: я не «академический» разработчик. До последнего года писал на Python в основном чтобы прочитать чужой скрипт и подправить отступ. То, что вы увидите в коде ниже — собирал руками, лезя в документацию по каждому слою. Поэтому это не «гайд от эксперта», а скорее дневник развилок — где я выбрал так и так и почему. Если у вас опыт [1] глубже и я где-то перегнул палку или упустил — буду благодарен за поправки в комментариях, для меня это самая ценная часть таких публикаций.

Никаких ссылок, кодов промокодов и «закажите у нас» — просто разбор.


TL;DR

Сделал ИИ-агента для небольшой студии дизайна интерьера. Делает две вещи:

  • Чат на сайте — отвечает на типовые вопросы про услуги, тарифы, сроки, мягко переводит на встречу с дизайнером.

  • Эндпоинт /brief — клиент заполняет короткий бриф через форму, на выходе получает три заметно разных концепции интерьера: палитра, материалы, мебель, свет, четыре фото из Pexels на каждую.

Стек: Claude Haiku 4.5 для чата, Claude Sonnet 4.6 для генерации концепций, FastAPI на Railway, Pexels API для фото, статичный фронт на VPS. Без LangChain, без LlamaIndex, без векторной базы, без RAG-фреймворка. Один файл main.py на 712 строк, два промпта, четыре эндпоинта.

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


Контекст

Заказ: у знакомой — небольшая студия дизайна интерьера. Один дизайнер, проектов в работе одновременно три-четыре. Бюджет на разработку — несколько рабочих дней (это я сам себе ставил, у нас был дружеский договор). Боль [2] на входе воронки понятная: клиенты пишут в WhatsApp в одиннадцать вечера, утром половина уже у конкурентов, потому что никто им не ответил. И вторая боль — клиент часто сам не понимает, чего хочет, и приходит на встречу «расскажите мне что-нибудь».

Из этих двух болей выросли две сущности:

  1. Чат-агент — отвечает мгновенно ночью, не оставляет сообщения «висеть до утра».

  2. /brief — генератор трёх концепций по короткому брифу. Не заменяет дизайнера, а готовит первую встречу: клиент приходит уже с понятием, какое направление откликается.

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


Развилка №1: брать ли LangChain

Начинал я с распространённого представления, что любой ИИ-агент = LangChain (для оркестрации) + векторная база (Chroma/Qdrant/Pinecone) для контекста + RAG-цепочка для актуальных данных + агент-роутер с тулами. Так пишут в большинстве гайдов и так делают «взрослые». Хотел тащить это в проект, потому что страшно было пилить «не как у людей».

Прежде чем тащить — сел и расписал, что из этого реально решает мою задачу. Получилось вот что:

  • Оркестрация цепочек? У меня одна цепочка: сообщение → один запрос к LLM → ответ. Никаких ветвлений, параллельных шагов, ретраев с разными моделями. LangChain тут — обёртка вокруг httpx.post().

  • RAG для тарифов и услуг? Весь контент студии помещается в 2,5 тысячи токенов системного промпта. Это меньше, чем один embedding-запрос в Pinecone. И главное — этот контент не меняется каждую неделю. Тарифы — раз в квартал, услуги ещё реже.

  • Векторная база? Под что? Под историю диалога — сессии короткие, 5–10 сообщений, помещаются в окно. Под услуги — их семь штук. Под похожих клиентов — у дизайнера 30 проектов в год, векторный поиск тут неуместен по размерности.

  • Агент-роутер с тулами? Чат не должен никуда ходить во внешний мир — ни в календарь, ни в CRM, ни в базу. У /brief есть один тул (поиск фото в Pexels), и он жёстко привязан к структуре ответа, не выбирается агентом.

Когда сложил это в табличку, оказалось — из всех абстракций LangChain я бы использовал ровно одну, ChatAnthropic как обёртку над HTTP-клиентом. И эта обёртка добавляет: зависимость на ~500 МБ, новый слой с собственными багами, версионную нестабильность (LangChain известен breaking changes между минорными релизами), новый язык описания цепочек, который пришлось бы учить.

В обмен — chain.invoke() вместо прямого POST. Всё.

Никакого LangChain.

Это не значит, что LangChain — плохой инструмент. Это значит, что для узких задач с одной цепочкой он избыточен. Граница, на которой он начинает окупаться: 3+ параллельных цепочки, реальный роутинг между моделями, сложный multi-step агент с тулами. Если у вас одно «вопрос → ответ» — берите голый HTTP.

Это не моё гениальное озарение [3] — это просто результат честного разбора задачи. Если у вас контр-пример, когда LangChain заметно окупился именно на простой задаче, очень интересно его услышать, я могу что-то упускать.


Системный промпт вместо RAG

Раз весь контент студии помещается в SYSTEM, я просто положил его туда. Структура промпта — не «творческий текст», а строгий FAQ-документ. Ниже укороченный фрагмент (полный — около 5500 токенов вместе с эталонами ответов):

Ты — ассистент студии дизайна интерьера. Отвечай вежливо, по делу,
в спокойном профессиональном тоне. Без лишних эмодзи. Только на русском.
Короткие чёткие ответы.

О СТУДИИ:
- Дизайн интерьера жилых пространств в Москве
- Сайт студии и контакты — см. правила маршрутизации ниже

УСЛУГИ:
1. Функциональное планирование — планировочные решения, перепланировки
2. Дизайн-проект — цельный визуальный образ, материалы, рабочая логика
3. Рабочая документация — чертежи и технические решения
...

ТАРИФЫ:
Три тарифа с разной глубиной проработки. Включают замер, фотофиксацию
и договор. Подробности — на сайте студии (правила маршрутизации ниже).

ПРАВИЛА:
- Вопрос о записи/консультации → дать контакт студии
- Вопрос о цене → объяснить тариф и что входит, без точных цифр
  если клиент не уточнил параметры объекта
- Хочет посмотреть варианты / не знает чего хочет → предложи /brief
- Не придумывай информацию которой нет выше

Подсвечу важное: разделы написаны человеческим языком в правильной структуре. «УСЛУГИ» — нумерованный список с одной строкой описания. «ТАРИФЫ» — словесное описание уровней без точных сумм в промпте (это спорное решение, у нас тарифы менялись пару раз за квартал, и я не хотел перекатывать SYSTEM каждый раз). «ПРАВИЛА» — однозначная маршрутизация типовых интентов.

Модель в такой структуре не теряется. Когда клиент спрашивает «сколько стоит планировка», Haiku видит, что «планировочное решение» упомянуто в услугах, и отвечает связно. Если бы тот же контент я залил в Chroma чанками по 512 токенов и доставал через RAG, я бы получил тот же результат, но: с задержкой на embedding-запрос, риском «не доехал нужный чанк», необходимостью поддерживать векторную базу как отдельный сервис. Зачем — я честно не нашёл ответа.


Эндпоинт /chat целиком

Это полный эндпоинт чата. Он короче, чем README типичного LangChain-стартера:

@app.post("/chat")
async def chat(request: Request):
    body = await request.json()
    messages = body.get("messages", [])
    if not messages:
        return JSONResponse({"error": "messages is empty"}, status_code=400)

    async with httpx.AsyncClient(timeout=60) as client:
        response = await client.post(
            "https://api.anthropic.com/v1/messages",
            headers={
                "x-api-key": ANTHROPIC_API_KEY,
                "anthropic-version": "2023-06-01",
                "content-type": "application/json",
            },
            json={
                "model": "claude-haiku-4-5-20251001",
                "max_tokens": 2000,
                "system": [{
                    "type": "text",
                    "text": SYSTEM,
                    "cache_control": {"type": "ephemeral"},
                }],
                "messages": messages,
            },
        )
        data = response.json()

    text = "".join(
        b.get("text", "") for b in data.get("content", []) if b.get("type") == "text"
    ).strip()
    return JSONResponse({"reply": text, "usage": data.get("usage")})

Разберу несколько решений по этому коду:

Модель claude-haiku-4-5-20251001. Самый маленький Claude — быстрый, дешёвый, по нашим задачам (короткие ответы по плотному FAQ) не уступает Sonnet. Время первого токена — ~600 мс, полного ответа — 1–2 секунды. Стоимость на нашем трафике — около копейки за диалог.

max_tokens=2000. Запас, который реально не используется — типичный ответ помещается в 100–300 токенов. Поставил с резервом на случай «расскажи подробно про каждый тариф».

system как список объектов с cache_control. Это включение prompt caching у Anthropic. Если SYSTEM-промпт не меняется между запросами, API его кэширует, повторные запросы считают только новые сообщения. Хит даёт скидку 90% на input-токены и режет латентность первого токена в 2 раза. Про грабли этого механизма дальше отдельный раздел.

messages приходит целиком от клиента. История диалога хранится во фронтенде в localStorage, не на сервере. Это осознанное упрощение: пока нет аутентификации и нет необходимости хранить переписку, не хочется мучиться с базой и доступами. Когда понадобится — добавлю SQLAlchemy и одну таблицу.

Никакого retry, fallback, circuit breaker. Anthropic стабилен — за квартал ~99,95% успешных запросов. Заворачивать в tenacity с пятью попытками — преждевременная оптимизация. Если упадёт — клиент перезагрузит страницу.

Это «минимально достаточный код». Один файл, одна функция, прямой запрос. Тесты пишутся за пять минут — мокаешь httpx.AsyncClient и проверяешь, что отправляется правильный body.


Главное открытие: FAQ-эталоны вместо чёрного списка запретов

Самой нетривиальной частью оказалось не научить ассистента отвечать, а научить молчать. Первые версии фантазировали: обещали невозможные сроки, путали тарифы, со второго сообщения начинали продавать встречу. То, что для меня казалось «модель должна сама понять, что это плохо» — она не понимала.

Первый порыв — добавить чёрный список:

ЗАПРЕТЫ:
- Не обещай сроки меньше 2 месяцев
- Не предлагай встречу до того, как узнал площадь
- Не используй слова «гарантирую», «точно», «безусловно»
- Не упоминай конкурентов
- Не давай скидок
- Не пиши маркированными списками, только связным текстом
...

Это не работало. К концу второй недели у меня было 23 пункта запретов. Ассистент всё равно их нарушал через раз, а сам промпт превратился в нечитаемое полотно «не делай X». И ещё тонкая вещь, которую я заметил: чёрные списки в принципе ухудшают качество ответов — модель будто фокусируется на «как обойти запреты» вместо «как помочь клиенту».

Переломный момент — переход на FAQ-эталоны в самом теле SYSTEM. Вместо «не делай так» — «вот эталонный ответ на типовой вопрос». Структура такая:

ВОПРОС: Сколько стоит проект двушки?
ОТВЕТ-ЭТАЛОН: «Зависит от тарифа и площади. У нас три уровня
проработки. Если назовёте метраж, могу подсказать ориентир по
каждому. Если интересно, могу подсказать, какой подходит под
вашу задачу».

ВОПРОС: Когда вы свободны на консультацию?
ОТВЕТ-ЭТАЛОН: «Запись на встречу — через контакт студии,
дизайнер ответит в течение дня и согласует время напрямую».

ВОПРОС: А вы можете спроектировать всё без меня, я не понимаю в дизайне?
ОТВЕТ-ЭТАЛОН: «Полностью без вас — не получится, ваши предпочтения
и образ жизни нужны как материал. Но если непонятно с чего начать,
у нас на сайте есть бесплатная концепция — за минуту собирается
три направления, можно посмотреть, что откликается».

Эта схема резко улучшила сдержанность. Модель видит готовый паттерн — длину ответа, тон, структуру, способ обработки ситуации — и воспроизводит его на похожих вопросах. Чёрный список из 23 пунктов схлопнулся в 4 правила маршрутизации (раздел «ПРАВИЛА» выше).

Почему это работает? Моя рабочая гипотеза: LLM — это машина имитации паттернов, а не машина следования инструкциям. Когда говоришь «не делай X», у модели нет образца того, что делать вместо X — она просто стохастически снижает вероятность токенов, связанных с X. Когда даёшь эталонный пример, она тиражирует его стилистически. Эталон — это положительный пример, чёрный список — отрицательный, и для имитативных моделей положительные примеры эффективнее.

Это не моё открытие — про важность few-shot examples писано тысячу раз. Что было откровением лично для меня — что 10–15 эталонов внутри SYSTEM работают лучше, чем 50 запретов и 5 эталонов отдельно. Эталоны делают всю тяжёлую работу.


Грабли с порогом кэширования 4096 у Haiku 4.5

Anthropic в 2024 году выкатил prompt caching. Если SYSTEM-промпт длинный и стабильный, API его кэширует на сервере, повторные запросы платят только за uncached input. На длинных промптах — до 90% экономии и латентность первого токена режется в 2 раза.

Я разметил кэширование в /chat сразу:

"system": [{
    "type": "text",
    "text": SYSTEM,
    "cache_control": {"type": "ephemeral"},
}],

И смотрю на usage в ответах API — cache_creation_input_tokens и cache_read_input_tokens стабильно нули. Кэш не работает. Я месяц думал, что у меня баг в коде. Проверял версии API, разрешения, ставил debug-логи. Никаких ошибок.

Оказалось — у Haiku 4.5 минимальный размер кэшируемого блока 4096 токенов. У Sonnet и Opus — 1024. Если блок короче — Anthropic просто тихо игнорирует cache_control, без warning, без ошибки [4] в ответе. Нигде это не подсвечено крупно в документации, нашёл в одной строке в таблице параметров кэширования.

Мой SYSTEM на момент проблемы был ~2500 токенов. Для Sonnet кэш бы работал, для Haiku — нет. Было два варианта:

  1. Раздуть SYSTEM до 4096+, добавив FAQ-эталоны и подробные правила. Это улучшает качество ответов в любом случае (см. предыдущий раздел), плюс активирует кэш.

  2. Переключиться на Sonnet. Дороже, медленнее, для нашего чата избыточен.

Выбрал первый. Сейчас SYSTEM — ~5500 токенов, кэш активен. На каждом запросе вижу:

"usage": {
  "input_tokens": 47,
  "cache_creation_input_tokens": 0,
  "cache_read_input_tokens": 5483,
  "output_tokens": 178
}

Экономия на 1000 диалогах: вместо 5,5 млн input-токенов почти всё считается как cached, цена режется примерно в 10 раз.

Что забрать: если активируете caching на Haiku — следите, чтобы блок был ≥4096 токенов, иначе тихо ничего не работает. Для Sonnet и Opus порог 1024. Это, мне кажется, должно быть в документации красным жирным шрифтом, но пока нет.


Эндпоинт /brief: структурированный ответ от Sonnet 4.6

Второй эндпоинт сложнее. От /chat отличается двумя вещами:

  • здесь нужен Sonnet 4.6 (не Haiku) — задача креативная, нужен качественный язык и заметная разница между концепциями;

  • ответ должен быть строго JSON-массивом, без markdown-обёрток, парсимый напрямую.

Промпт начинается так:

Ты — арт-директор студии интерьерного дизайна.
Студия: тёплый минимализм, Japandi, скандинавский, функциональное
проектирование жилых пространств.

Тебе приходит бриф клиента. Твоя задача — выдать ТРИ заметно разных
концепт-направления для обсуждения с клиентом.

Отвечай СТРОГО валидным JSON-массивом без markdown-обёртки и без
комментариев. Никакого текста до или после JSON.

Структура каждого направления:
{
  "name": "Название концепции (2-4 слова, на русском)",
  "tagline": "Одна строка — суть атмосферы",
  "palette": [
    {"hex": "#XXXXXX", "name": "название цвета"},
    ... ровно 5 цветов
  ],
  "materials": [...5-6 материалов с конкретикой...],
  "furniture": [...5-6 предметов...],
  "lighting": "температура, источники, акценты",
  "mood": "что чувствует человек, время дня, звуки",
  "image_prompts": [...4 prompt-а на английском...],
  "pexels_queries": [...4 поисковых запроса для Pexels...]
}

Несмотря на жёсткие инструкции «без markdown», Sonnet периодически оборачивает ответ в ```json … ```. Не всегда, в 5–10% случаев. Бороться с этим через prompt engineering можно — но дешевле просто прибрать на парсинге:

def _parse_concepts(text: str):
    text = text.strip()
    if text.startswith("```"):
        text = re.sub(r"^```(?:json)?s*", "", text)
        text = re.sub(r"s*```$", "", text)
    return json.loads(text)

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


Pexels вместо генерации картинок: почему живое фото бьёт DALL-E

Концепция без визуала — это полотно текста, которое клиент не дочитает. С визуалом — оживает. Первый вариант, который я попробовал — генерация картинок через DALL-E 3 / Midjourney через API. Получалось красиво, но узнаваемо неживо: у AI-генерации в 2026 году всё ещё характерные артефакты — слишком чистая геометрия, неестественные текстуры, странные углы между плинтусом и стеной. Любой, кто видел реальный интерьер на фото, считывает «это не настоящее» за секунду.

Переключился на Pexels API. Это бесплатный сток с реальной фотографией: 200 запросов/час, 20 000/месяц, без оплаты для коммерческого использования.

Логика [5]: Sonnet кроме описаний выдаёт 4 коротких поисковых запроса для каждой концепции:

"pexels_queries": [
  "japandi living room",
  "warm wood texture",
  "linen sofa detail",
  "beige minimalist interior"
]

И параллельно через asyncio.gather тянем 4 фото:

async def fetch_pexels_set(queries, prompts, randomize=False):
    queries = (queries or [])[:4]
    async with httpx.AsyncClient() as client:
        results = await asyncio.gather(
            *[fetch_pexels(client, q, randomize=randomize) for q in queries]
        )
    return [
        {
            "prompt": prompts[i],
            "query": queries[i],
            "url": (r or {}).get("url"),
            "photographer": (r or {}).get("photographer"),
            "page": (r or {}).get("page"),
        }
        for i, r in enumerate(results)
    ]

В каждой концепции — 4 живых фото по теме, с указанием фотографа и ссылкой на оригинал (этого требует лицензия Pexels).

Что забрать: для интерьеров, фуд-фото, путешествий, моды — берите Pexels/Unsplash вместо генерации. Дешевле, быстрее, главное — выглядит как настоящее. Генерация выигрывает там, где нужна абсолютная уникальность сцены (фантастика, дизайн упаковки, иллюстрации к чему-то нестандартному), а не там, где нужна правдоподобность.


Микро-урок про форму: чипсы вместо текстовых полей

Маленький, но важный UX-урок — не про модели, про форму. Изначально все поля брифа были textarea — «опишите образ жизни», «опишите свет в комнате», «что вам не нравится». Около половины клиентов застревали на «образе жизни» и закрывали вкладку. Текстовое поле в форме — это психологический барьер: надо сформулировать, проверить грамматику, бояться написать глупость.

Заменил почти все поля на чипсы — кнопки с предзаготовленными вариантами. Для «Кто живёт»: «один», «пара», «пара + ребёнок», «пара + 2 детей», «несколько поколений». Для «Бюджет»: «эконом», «средний», «комфорт», «премиум». Для «Стиль-ориентир»: «минимализм», «Japandi», «скандинавский», «современная классика», «лофт», «эклектика», «не знаю».

Чипсы дополнены опциональным текстовым полем. Заполняемость формы выросла в 2,5–3 раза. Сигнал для модели чуть упростился, но это компенсируется тем, что до неё вообще доходит больше клиентов.

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


Минимальный стек целиком

┌─ Frontend ───────────────────────────────────────────┐
│ Статичный HTML/Next.js, лежит на VPS                 │
│ Виджет чата — fixed-кнопка справа снизу              │
│ Страница /brief — форма с чипсами + результат        │
└──────────────────────────────────────────────────────┘
                       │ POST
                       ▼
┌─ Backend ────────────────────────────────────────────┐
│ FastAPI на Railway, один файл main.py (712 строк)    │
│                                                      │
│ POST /chat              → Claude Haiku 4.5            │
│ POST /brief             → Claude Sonnet 4.6 + Pexels  │
│ POST /regenerate-images → только Pexels               │
└──────────────────────────────────────────────────────┘
                       │
            ┌──────────┴──────────┐
            ▼                     ▼
       Anthropic              Pexels
       (LLM)                  (фото)

Никаких баз данных. Никаких очередей. Никаких воркеров. Деплой — git push, Railway сам ребилдит контейнер за минуту-две.


Где этот подход начнёт ломаться

Чтобы статья не выглядела «как мы выкинули весь enterprise и заиграли» — честно скажу, где минимально достаточный перестаёт быть достаточным.

1. Если контент перестаёт помещаться в SYSTEM. Допустим, появилось 500 кейсов, каждый со своим описанием, и хочется, чтобы агент про них вспоминал в нужный момент. 500 кейсов в SYSTEM не лезут — приходит RAG. Тогда же приходит embedding, векторная база, индексация, инвалидация при обновлении. Это уже отдельная инфраструктура.

2. Если появляется multi-step рассуждение. Например, «собери концепцию, проверь, нет ли в ней цветов из стоп-листа, если есть — переделай, потом подбери фото». Сейчас одношаговый pipeline. Если шагов становится 3+ — стоит подумать про оркестрацию (LangGraph, или просто аккуратный async/await).

3. Если нужны тулы. Например, агент смотрит в Google Calendar дизайнера, находит свободные слоты, предлагает три времени. Это тулы. Можно руками через Anthropic function calling. Если тулов 2–3 — руками. Если 10+ — есть смысл смотреть в сторону агентских фреймворков, но я бы сначала попробовал Claude Tool Use напрямую.

4. Если появляется состояние между сессиями. История диалога, профиль клиента, прогресс воронки — это БД, скорее всего Postgres + ORM. У меня этого нет осознанно: история в localStorage, новый клиент = новый разговор.

5. Если нужна команда из трёх и более человек. Минимально достаточный код легко поддерживать одному. Когда подключаются ещё двое — нужны соглашения, шаблоны, абстракции. Тут LangChain/типизированные цепочки/Pydantic-схемы окупаются. Не из-за технических причин, а из-за общего языка в команде.

«Минимально достаточный» — это не идеология. Это состояние, в котором находится проект сейчас. Через год эта же кодовая база может потребовать LangChain — и это будет нормально. Главное — не тащить его за полгода до того момента, когда он действительно нужен.


Что бы сделал по-другому

Если бы запускался сегодня с нуля:

  • Логи запросов в SQLite с самого начала. Сейчас история не сохраняется нигде, и через два месяца не могу пересмотреть «как же там ассистент ответил тому клиенту, который потом стал заказчиком». Пять строк кода, надо было делать сразу.

  • Метрика прерванных диалогов. Знать, на каком сообщении клиент закрыл виджет — золотой источник для тюнинга промпта. Веду эту работу глазами по выгрузкам, что не очень.

  • A/B на SYSTEM-промпте. Правки промпта летят в прод без сравнения с предыдущей версией. Один эндпоинт с двумя версиями и подсчётом конверсии — пара часов работы, окупится за месяц.

  • Не пытался бы сделать «универсальный бот». Узкий ассистент с понятной границей ответственности — это единственное, что у меня уверенно заработало. Любая попытка «давайте он ещё и Х» приводила к падению качества по основной задаче.


Вместо вывода

Когда смотришь на современный AI-ландшафт, кажется, что любой агент = LangChain + векторка + RAG + observability + оркестрация. Иногда это правда. Чаще — это гипотеза, которая не выдерживает встречи с реальной задачей.

Стоит честно сесть и спросить себя по каждому слою: что именно эта абстракция решает в моей задаче и сколько мне будет стоить её отсутствие. У меня по большинству слоёв стоимость отсутствия оказалась — ноль. И когда я перестал тащить их «потому что так делают все», вылезло, что вся работа делается в одном файле, читается за вечер и спокойно поддерживается одним человеком.

Это не призыв всё писать руками — фреймворки существуют не просто так. Это призыв не путать сложность инструмента со сложностью задачи. Иногда задача — простая, и тогда простой стек её решает быстрее, дешевле и надёжнее.


Буду рад содержательным комментариям. Особенно интересны два кейса: где LangChain у вас действительно окупился — нужны контр-примеры, чтобы лучше калибровать совет; и где минимально достаточный стек у вас, наоборот, треснул через полгода — на каких именно границах. Спасибо, если дочитали.

Автор: eignatiev

Источник [6]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/32514

URLs in this post:

[1] опыт: http://www.braintools.ru/article/6952

[2] Боль: http://www.braintools.ru/article/9901

[3] озарение: http://www.braintools.ru/article/7570

[4] ошибки: http://www.braintools.ru/article/4192

[5] Логика: http://www.braintools.ru/article/7640

[6] Источник: https://habr.com/ru/articles/1054326/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1054326

www.BrainTools.ru

Rambler's Top100