Привет, Habr! Наша команда LLM-разработки подготовила статью о реальном практическом опыте тюнинга и тонкой настройке RAG-системы в области охраны труда. КаждыйПривет, Habr! Наша команда LLM-разработки подготовила статью о реальном практическом опыте тюнинга и тонкой настройке RAG-системы в области охраны труда. Каждый

Из «песочницы» в Production: как мы масштабировали RAG-систему для эксперта по охране труда

2026/02/17 15:26
17м. чтение

Привет, Habr! Наша команда LLM-разработки подготовила статью о реальном практическом опыте тюнинга и тонкой настройке RAG-системы в области охраны труда. Каждый, кто начинал работать с LLM, проходил через этот «медовый месяц»: вы берете LangChain, загружаете с десяток PDF-файлов в ChromaDB, пишете простенький промпт — и происходит магия. Бот отвечает, эксперты в восторге, MVP готов за выходные.

Но магия исчезает ровно в тот момент, когда в базу знаний прилетает тысяча документов, а цена ошибки из «просто забавной галлюцинации» превращается в юридические риски и штрафы. В нашем проекте «Марк» (протестировать тут: @AI_assistantOT_bot) — ИИ-эксперте по охране труда — мы столкнулись именно с этим: наивный RAG на больших данных не просто работает хуже, он разваливается.

Мы заглянем под капот системы, которая прошла путь от локального скрипта до сложной архитектуры на LangGraph.

Мы подробно разберем:

  • Почему классическая нарезка текста на чанки (Chunking) — это главный враг точности.

  • Как мы обнаружили «квантовый скачок» качества, поправив заголовки в ETL-пайплайне и увеличив точность нарезки на чанки.

  • Почему мы заменили медленный LLM-реранкер на специализированную NLP-модель и что это дало.

  • Как LangGraph помог нам превратить линейную цепочку в гибкий граф с циклами самокоррекции.

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

Если вы разработчик или ML-инженер, который прямо сейчас пытается вытащить свой RAG из состояния «он иногда ошибается», эта статья сэкономит вам пару месяцев жизни и кучу нервных клеток.

Этап MVP: Иллюзия работоспособности и архитектурный «наивный» RAG

На старте любого ML-проекта существует соблазн собрать систему из готовых блоков LangChain «по учебнику». Наш MVP не стал исключением. Первоначальная задача была амбициозной, но узкой: научить бота ориентироваться в паре десятков документов по охране труда. На малом объеме данных система демонстрировала впечатляющую точность, что создало опасную иллюзию масштабируемости.

Технический стек «песочницы»

Архитектура изначально строилась на таком конвейере:

  1. ChromaDB в качестве векторного хранилища.

  2. Sentence-transformers для генерации эмбеддингов.

  3. LLM-based Reranker: промпт, заставляющий модель оценивать релевантность чанков по шкале от 1 до 100.

  4. Gemma3 как основное ядро генерации.

Проблема №1: Инфраструктурный монолит и локальное хранение

Одной из главных архитектурных ошибок на этапе MVP стала неправильная настройка ChromaDB с параметром persist_directory непосредственно внутри директории приложения (./app/chroma_db). Мы использовали её в embedded-режиме (локально), не задействовав client-server возможности, что сделало базу данных частью кода.

Такой подход породил ряд критических проблем:

  • Трудности CI/CD: База знаний «весила» гигабайты и фактически мигрировала вместе с кодом, что делало деплой неповоротливым.

  • Отсутствие изоляции: Любая ошибка в путях или правах доступа в контейнере приводила к потере доступа к индексам.

  • Масштабируемость: Параллельный доступ нескольких воркеров к одной локальной файловой базе ChromaDB приводил к блокировкам и деградации производительности.

Мы не сразу перешли на Qdrant или client-server ChromaDB, потому что на ранних этапах MVP объём данных был небольшим (несколько десятков документов), и embedded-режим позволял быстро прототипировать. Мы тестировали client-server ChromaDB, но столкнулись с дополнительными сложностями в настройке (интеграция с Docker, управление портами), и решили отложить миграцию, чтобы не замедлять разработку.

Проблема №2: «Слепая» нарезка на чанки (Naive Chunking)

В MVP использовался стандартный RecursiveCharacterTextSplitter. Проблема заключалась в том, что алгоритм учитывал лишь количество символов и разделители абзацев, полностью игнорируя семантическую структуру документов по охране труда.

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

  • Чанки обрывались на середине логических инструкций.

  • Метаданные (номера страниц, названия приказов) пробрасывались фрагментарно.

  • Система поиска выдавала «куски текста», из которых LLM физически не могла собрать юридически верный ответ.

Проблема №3: Реранкер как «бутылочное горлышко»

Для повышения точности мы внедрили этап переранжирования (Reranking). Однако на этапе MVP это было реализовано через дополнительный вызов LLM. Мы просили модель: «Оцени релевантность данного текста запросу пользователя от 1 до 100».

Это решение обладало крайне низкой эффективностью:

  1. Latency: Каждый запрос требовал 5–10 дополнительных секунд на скоринг топ-к документов.

  2. Нестабильность: Модель могла выставить «80» одному документу и «40» его точному дубликату из-за специфики внимания (attention) и галлюцинаций.

  3. Стоимость ресурсов: Тратить контекстное окно и вычислительные мощности основной модели на простую сортировку — непозволительная роскошь для Production-системы.

Итог этапа: Точка невозврата

Пока база данных ограничивалась 50–100 документами, векторный поиск (Cosine Similarity) успешно находил нужные фрагменты даже при «кривой» нарезке. Но как только объем знаний перешагнул порог в несколько тысяч файлов, «шум» в выдаче стал критическим. Система начала страдать от классической проблемы: релевантный контекст вымывался из топ-выдачи нерелевантными, но семантически похожими фрагментами.

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

3. Кризис роста: Почему система начала «разваливаться»

Когда объем базы знаний перевалил за критическую отметку в несколько тысяч документов, наш «уютный» MVP начал выдавать ответы, которые заставляли экспертов по охране труда хвататься за голову.

Симптомы «отравления» данными

  1. Деградация Precision/Recall: Векторный поиск стал возвращать слишком много «шума». Похожие по смыслу, но разные по юридической сути инструкции начали перекрывать друг друга.

  2. Феномен «Lost in the Middle»: Мы заметили, что если релевантный кусок текста оказывался в середине контекстного окна, LLM часто его игнорировала. При росте базы нам приходилось увеличивать k (количество чанков), что только усугубляло проблему.

  3. Задержки (Latency): Наш LLM-реранкер превратился в «пробку». Ожидание ответа в 15–20 секунд убивало всякую лояльность пользователей.

Временный «костыль»: Разделение баз

В попытке спасти точность мы пошли на костыль — разделили информацию по разным базам данных (отдельно нормативка, отдельно внутренние шаблоны). Точность выросла, так как уменьшилось пространство поиска, но UX пострадал. Бот стал отвечать еще дольше, а логика переключения между базами превратилась в «спагетти-код».

LLM-as-a-judge: Суровый судья

Чтобы объективно измерить масштаб катастрофы, мы внедрили систему автоматической оценки качества. Мы использовали Qwen (30B) для роли судьи.

  • Схема: Модель получала «Вопрос» — «Эталонный ответ» — «Ответ системы».

  • Первый блин комом: Изначально Qwen судила слишком жестко, ставя низкие баллы за синонимы или иную структуру предложения. Нам пришлось пройти через десятки итераций промпт-инжиниринга, чтобы «калибровать» судью. Также есть методики для оценки качества работы самого судьи.

Важный инсайт: Без настроенной метрики (даже несовершенной) оптимизировать RAG — это крайне неэффективное дело.

4. Глубокая модернизация ETL: С этого начинается Production

После сотен тестов мы пришли к горькому, но важному выводу. Как бы мы ни тюнили промпты, работала золотая заповедь Data Science:

GIGO (Garbage In — Garbage Out): Мусор на входе — мусор на выходе.

Никакая продвинутая LLM не спасет, если в нее подают криво нарезанные куски текста без контекста. Мы начали полную перестройку ETL-пайплайна. Конечно, промпт-инжиниринг даёт быстрый буст (как видно из наших метрик на этапе 1), потому что он помогает модели лучше интерпретировать даже "сырые" данные. Но это временный хак: настоящий скачок качества приходит от работы с данными (80% успеха — в ETL и чанкинге, 20% — в моделях и промптах). Промпты маскируют проблемы с данными, но не решают их — в долгосрочной перспективе данные доминируют.

Очистка и структурирование: extract_structured

Мы отказались от прямого чтения PDF/DOCX как «потока символов». Наш новый пайплайн теперь выглядит так:

  1. Raw Extraction: Извлечение текста с сохранением координат блоков.

  2. Logic Build: Переход к цепочке extract_structured -> build_elements -> build_chunks.

  3. Детекция иерархии: Мы научили систему распознавать заголовки разделов. Теперь каждый чанк «знает», к какой главе и пункту он относится.

Умный Chunking и дедупликация

Мы отошли от фиксированного размера окна. Теперь чанк формируется с учетом логических границ абзацев и списков.

  • Настройка Overlap: Мы подобрали оптимальный размер перекрытия, чтобы смысловые связи между чанками не терялись.

  • Дедупликация (threshold=0.92): При росте базы в нее неизбежно попадают дубликаты или очень похожие редакции документов. Мы внедрили механизм дедупликации на этапе эмбеддингов, что сократило размер индекса и уменьшило «замусоривание» выдачи одинаковыми результатами.

Инженерный подход к индексации: Переход на Qdrant

Мы поняли, что наша начальная настройка ChromaDB в embedded-режиме не масштабируется при росте данных. После тестирования альтернатив (включая client-server ChromaDB) мы выбрали Qdrant за его удобство в production, и вот почему это изменило всё:

  • Client-Server Архитектура: Мы вынесли векторную базу в отдельный сервис. Это позволило обновлять код бота, не трогая индексы, и дало возможность горизонтального масштабирования.

  • Скорость и Payload: Qdrant эффективнее работает с метаданными. Мы смогли хранить не только векторы, но и богатый контекст (названия файлов, номера страниц, теги) прямо в «полезной нагрузке» (payload) точек, что ускорило фильтрацию в разы.

  • Параллелизация и батчинг:

    • Мы внедрили многопоточную обработку (Workers=5), где каждый воркер независимо готовит эмбеддинги.

    • Батчевая загрузка: Теперь данные улетают в Qdrant пакетами по 256 записей, что минимизирует накладные расходы на сетевые запросы.

    • Retry with Backoff: Ошибки сети или временные перегрузки API больше не «роняют» процесс индексации — система корректно пробует повторить операцию, не дублируя данные.

  • Разделение коллекций: В Qdrant мы легко реализовали логическое разделение на коллекции (основная база знаний и шаблоны документов), сохранив при этом единую инфраструктуру доступа.

Метаданные как спасение: подмешивание fileName

Одной из полезных фич стала проброска метаданных. При поиске шаблонов документов (заявлений, актов) мы обнаружили, что семантический поиск по тексту самого шаблона работает плохо (они все похожи).

Решение: Мы начали учитывать fileName при поиске. Если пользователь ищет «Акт о несчастном случае», поиск по названию файла дает +40% к точности попадания в нужный шаблон по сравнению с чисто векторным поиском по содержимому.

5. Эволюция поиска: Гибридная схема и Query Expansion

Загрузив данные в векторную базу, мы столкнулись с новой проблемой. Векторный поиск (Dense Retrieval) отлично понимает смыслы и концепции (например, связь слов «травма» и «несчастный случай»), но отвратительно работает с точными совпадениями.

Когда пользователь искал конкретный «Приказ № 33н», векторный поиск часто выдавал документы с похожими номерами или просто другие приказы по той же теме, игнорируя точное вхождение.

Hybrid Search: Векторы + Ключевые слова

Мы поняли, что RAG не может жить на одних векторах. Мы внедрили гибридный поиск, объединив два подхода:

  1. Vector Search (Cosine Similarity): Отвечает за семантику («О чем пользователь хотел спросить?»).

  2. BM25 (Keyword Search): Старый добрый алгоритм, который ищет точные совпадения слов («Какие конкретно термины использовал пользователь?»).

Мы использовали EnsembleRetriever из LangChain, настроив веса: 0.6 для векторов и 0.4 для BM25. Этот баланс позволил нам находить документы, которые написаны сложным юридическим языком, но содержат конкретные номера статей и приказов.

Query Expansion: Борьба с «плохими» вопросами

Пользователи редко формулируют запросы как юристы. Вместо «Обеспечение СИЗ при работе на высоте согласно правилам» они пишут: «нужны ли каски на крыше». Векторному поиску сложно сопоставить «крышу» с «работами на высоте» без контекста.

Мы внедрили этап расширения запроса (Query Expansion). Перед поиском мы просим быструю LLM (Gemma 3:12b) сгенерировать 3 вариации исходного вопроса пользователя: одну более формальную, одну с синонимами и одну, разбитую на подзадачи. Поиск ведется сразу по всем вариантам, что кратно повышает шанс зацепить нужный контекст.

Merging: Склеиваем контекст обратно

Из-за нарезки на чанки часто случалось так, что начало мыли находилось в конце страницы 10, а её завершение — в начале страницы 11. Ретривер мог вытащить оба куска, но в контекст LLM они попадали как разрозненные фрагменты.

Мы написали механизм Merging. Если в выдачу попадают чанки, которые в исходном документе идут подряд, система «склеивает» их обратно в единый блок текста перед подачей в генератор. Это позволило LLM видеть целостную картину, а не «лоскутное одеяло» из обрывков фраз.

6. Reranker: От LLM-скоринга к специализированным моделям

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

Провал LLM-реранкера

В MVP мы использовали «наивный» реранкер: просили LLM оценить каждый документ по шкале от 1 до 100.

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

  • Запредельная задержка (Latency): Оценка 20 документов через вызов LLM добавляла к ответу 5–10 секунд. В продакшене это неприемлемо.

  • Нестабильность (Variance): Одна и та же модель могла выставить разные баллы одному и тому же документу в зависимости от температуры и порядка чанков в промпте.

  • Бинарность мышления: LLM часто «жалела» документы, выставляя средние баллы там, где специализированная модель увидела бы полное отсутствие семантической связи.

Это решение работало на малом объёме, но не масштабировалось. Для reranking (скоринг большого набора кандидатов) лучше подходят специализированные модели.

Мы перешли на использование специализированной Cross-Encoder модели — BAAI/bge-reranker-v2-m3. В отличие от Bi-Encoder (где вектор запроса и документа сравниваются по косинусному сходству), Cross-Encoder пропускает запрос и документ через модель одновременно, что позволяет выявлять тончайшие семантические связи.

Это идеально для reranking: быстро (миллисекунды на чанк) и точные scores. Однако для последующей grading (бинарной проверки релевантности) в LangGraph мы используем LLM, но только на топ-чанкax после reranker'а (3–5 штук), с лёгкой моделью (Gemma 3:12B). Grading — это не scoring множества, а финальный домен-специфичный чек (учёт нюансов охраны труда, где cross-encoder может упустить контекст), поэтому LLM здесь дополняет, а не заменяет, минимизируя latency.

7. Оркестрация через LangGraph: Состояние вместо последовательности

Стандартный LangChain со своими Chains (цепочками) хорош для линейных задач. Но реальный RAG — это не линейный пайплайн, а сложный цикл с ветвлениями и проверками. Нам нужно было уметь возвращаться назад, если поиск ничего не нашел, или переспрашивать пользователя.

Почему Chains не хватило

Линейная логика не позволяла реализовать:

  1. Циклы: Если найденные документы не релевантны, нужно переписать поисковый запрос и попробовать снова.

  2. Условные переходы: Если вопрос касается шаблона документа, логика обработки должна идти по иному пути, чем при поиске в нормативке.

  3. Сохранение состояния: Нам требовался единый объект AgentState, который «путешествует» между узлами и накапливает контекст.

Наш граф состояний

Мы перенесли логику в LangGraph, разбив процесс на независимые узлы:

  1. Узел retrieve: Здесь происходит «магия» гибридного поиска (Vector + BM25) и расширение запроса (Query Expansion). На выходе мы получаем сырой набор кандидатов.

  2. Узел grade_documents: Это критически важный фильтр. Мы используем быструю LLM (Gemma 3:12B) как «судью», который проверяет каждый чанк на соответствие вопросу.

    • Если документ — «шум», он выбрасывается.

    • Если после фильтрации документов не осталось, граф уходит на цикл пересборки запроса. Это дополняет reranker из предыдущего этапа: cross-encoder (bge) даёт быстрые scores на большом наборе, а LLM — бинарный вердикт на топ-кандидатах, учитывая доменные нюансы (например, юридический контекст), где специализированная модель может быть менее гибкой. Latency минимально, так как объём мал.

  3. Узел generate: Только здесь, имея на руках проверенный и отранжированный контекст, основная модель (Gemma 3:27B) формирует итоговый ответ.

Обработка пустых результатов

Если поиск не дал результатов, система не извиняется сразу. Она активирует цикл: LLM анализирует, почему поиск провалился, генерирует 3 синонимичных варианта запроса и отправляет их обратно в узел retrieve. Это позволило нам отвечать на сложные, косвенные вопросы, которые раньше ставили бота в тупик.

Рис. 1. Обработка пустых результатов
Рис. 1. Обработка пустых результатов

8. Мозги системы: Ollama и выбор моделей

В качестве инференс-движка мы выбрали Ollama. Для open-source проекта это стандарт де-факто, позволяющий гибко управлять весами моделей и быстро переключаться между ними.

Gemma 3: Баланс между мощностью и скоростью

Мы остановились на семействе Gemma 3 от Google. Почему не Llama или Qwen? В наших тестах Gemma 3 показала лучшую работу с кириллицей в юридическом контексте и более строгое следование системным инструкциям.

Мы используем двухзвенную схему:

  • Gemma 3 (27b): Наш «тяжеловес». Используется исключительно в узле generate для синтеза итогового ответа. Она отлично справляется со сложной логикой и сохраняет формальный тон.

  • Gemma 3 (12b): Используется для «вспомогательных» задач — оценки релевантности документов и перефразирования запросов. Она в разы быстрее, что критически важно, так как эти операции выполняются в циклах.

Проблема циклической генерации

При работе с большими контекстами (когда мы подаем 10-15 чанков документов по ОТ) мы столкнулись с «зацикливанием»: модель начинала бесконечно повторять один и тот же абзац из постановления.

Как мы это лечили:

  1. Системный промпт: Ввели жесткую инструкцию: "Избегай повторений. Если информация уже приведена, не дублируй её. Пиши кратко и по существу".

  2. Параметры токенов: Мы тонко настроили repeat_penalty (установили на уровень 1.2) и top_p.

  3. Stop-последовательности: Добавили маркеры завершения, которые принудительно обрывают генерацию, если модель начинает «ходить по кругу».

Backend часть: FastAPI и PostgreSQL

Хотя RAG — это про ML, без надежного бэкенда он не взлетит.

  • FastAPI: Служит прослойкой между Telegram-ботом и LangGraph. Позволяет обрабатывать запросы асинхронно и собирать метрики.

  • PostgreSQL: Здесь мы храним не документы, а состояние диалога. Благодаря этому мы можем реализовывать полноценную память: пользователь может задать уточняющий вопрос («А что насчет СИЗ для этого случая?»), и система поймет, о каком «случае» шла речь в предыдущем сообщении, вытащив историю из БД. Возможно, для хранения состояния диалога не идеальное решение, но в рамках текущих задач вполне достаточное.

9. Валидация и Метрики: Как мы поняли, что стало лучше

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

Поэтому данные ниже охватывают лишь финальный этап нашей борьбы за качество. Мы использовали связку из метрик Context Precision, Context Recall и нашу кастомную метрику LLM-as-a-judge на базе Qwen 30B.

Context Precision оценивает качество ранжирования ретривером релевантных фрагментов контекста: метрика измеряет, насколько релевантные чанки размещены выше в списке retrieved contexts, и penalizes наличие нерелевантных элементов на высоких позициях. Релевантность каждого чанка определяется с помощью LLM (verdict: релевантен или нет) на основе сравнения с эталонным ответом.

Context Recall измеряет полноту извлечения релевантной информации: это доля утверждений (claims) из эталонного ответа (ground truth), которые могут быть атрибутированы (подтверждены) предоставленным retrieved context. Метрика использует эталонный ответ как прокси для идеального набора контекстов, разбивая его на отдельные claims и проверяя каждый с помощью LLM.

Хронология экспериментов и цифры

Мы разделили наш путь на четыре ключевых этапа. Результаты финальных тестов (5) показывают, как далеко мы ушли от первых правок. Важно отметить: мы проводили прогоны не строго итеративно (добавляя фичи по одной), а иногда изолированно или в комбинациях, чтобы оценить влияние каждого изменения отдельно. Поэтому метрики не всегда демонстрируют линейный рост — в некоторых случаях мы тестировали "чистый" эффект (например, только чанкинг без предыдущих промпт-фиксов), что могло привести к временным "спадам" по сравнению с предыдущим этапом. Кумулятивный эффект виден в финальном этапе.

Этап развития

Precision

Recall

LLM-Score

1. Фиксы промптов

0.6776

0.6984

0.7221

2. Исправление чанков

0.6730

0.7332

0.8359

3. Иерархические чанки

0.6999

0.8255

0.859

4. Тюнинг гиперпараметров

0.7130

0.7984

0.8511

5. Семантическое окно (LLM-chunking) в комбинации со всеми улучшениями

0.6759

0.7665

0.9218

Рис. 2. Динамика метрик в ходе улучшения пайплайна RAG
Рис. 2. Динамика метрик в ходе улучшения пайплайна RAG

Анализ результатов

  1. Промпты — это не панацея. Как видно из первого этапа, простое «вылизывание» инструкций давало неплохую точность (Precision), но модель часто не видела нужного контекста (Recall), а общая оценка судьи едва переваливала за 0.5.

  2. Архитектура данных решает. Переход на иерархические чанки (когда чанк знает своего «родителя» — заголовок раздела) совершил качественный скачок в оценке LLM-score (с 0.72 до 0.83). Бот перестал «нести отсебятину» и начал опираться на структуру документа.

  3. Игра с «дельтой» (Semantic Chunking). Нашим последним и самым успешным экспериментом стало внедрение механизма семантического окна. Мы использовали LLM для динамического формирования чанков: модель анализировала текст и, пока семантическая разница между новым предложением и текущим чанком не превышала заданную «дельту», чанк продолжал расти. Как только происходил смысловой разрыв — начинался новый чанк.

    • Итог: Хотя Precision немного просел из-за избыточности контекста, LLM-Score достиг 0.92. Ответы стали максимально полными и юридически выверенными.

Feedback Loop

Автоматика — это хорошо, но в охране труда последнее слово за человеком. Мы внедрили в интерфейс бота систему «дизлайков» с обязательным комментарием. Каждая такая жалоба попадает в отдельную очередь, анализируется, и на её основе обновляется наш тестовый датасет для LLM-as-a-judge.

10. Заключение: Чек-лист для тех, кто идет в Production

Путь от MVP до работающего решения в production показал, что RAG — это на 80% качественная работа с данными и лишь на 20% — подбор и тонкая настройка моделей. Если вы планируете масштабировать свою систему, предлагаем краткий чек-лист «выживания»:

• ETL важнее модели: плохо нарезанные или грязные данные не спасёт даже самая продвинутая модель. Инвестируйте время в иерархический чанкинг, метаданные и тщательную очистку.

• Гибридный поиск обязателен: dense-векторы отлично работают со смыслом, но BM25 (или другой sparse-метод) остаётся незаменимым, когда требуется точное совпадение номера приказа, конкретного термина или формулировки.

• Реранкер — must-have: никогда не скармливайте LLM весь массив найденных кусков. Специализированный реранкер (bge-reranker-v2-m3 и аналоги) существенно повышает точность и экономит токены / время ответа.

• LangGraph вместо линейных цепочек: если в логике появляется хотя бы один цикл (переформулировка запроса, уточнение, несколько итераций поиска), забудьте о простых LangChain-пайплайнах — переходите на графовый подход.

Этот набор технических решений лёг в основу нашего промышленного продукта — AI-эксперта по охране труда Марк (Telegram-бот: https://t.me/AI_assistantOT_bot).

Мы продолжаем развивать продукт и делиться нашим опытом в каналеhttps://t.me/dataundercontrol — там публикуем инсайты о новых релизах, их применимости в бизнесе, реальных кейсах и новостях.

Источник

Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу service@support.mexc.com для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.