Проблема: когда ChatGPT становится опасным для строительства
Представьте ситуацию: архитектор спрашивает у ChatGPT-4.5 (самая новая версия на февраль 2026 года) о минимальной ширине эвакуационного выхода. Модель уверенно отвечает: "1.2 метра". Звучит профессионально. Проблема в том, что в реальном СНиПе 21-01-97* указано 1.4 метра.
Разница в 20 сантиметров. На бумаге - ничего страшного. На практике - потенциальная угроза жизни людей при пожаре.
Технические галлюцинации - это не баг, а фундаментальное свойство генеративных моделей. Они создают правдоподобный текст, а не факты. В строительстве, медицине или юриспруденции такая "правдоподобность" становится опасной.
Именно эту проблему мы решали в проекте «Цифровой стандарт» - AI-инструменте для работы со строительными нормами. Задача: создать систему, которая никогда не выдумывает, а только цитирует реальные документы.
Решение: заменить память на поиск
Большинство разработчиков идут по простому пути: берут GPT-4.5 или Claude 3.7, пишут промпт "Ты эксперт по строительным нормам", и надеются на лучшее. Это гарантированный провал.
Правильный подход другой: модель не должна ничего "помнить" о нормах. Её задача - искать и синтезировать.
Архитектура выглядит так:
- Пользователь задает вопрос
- Система ищет релевантные фрагменты в векторной базе
- Найденные фрагменты + вопрос отправляются в LLM
- Модель формирует ответ ТОЛЬКО на основе предоставленных фрагментов
- Каждый факт в ответе привязан к конкретному документу с цитатой
Звучит просто? На практике - десятки подводных камней.
1 Подготовка данных: где нормативы превращаются в цифру
Сначала мы собрали все актуальные на 2026 год документы:
- СП (своды правил) - 156 документов
- СНиПы (строительные нормы и правила) - 87 документов
- ГОСТы - 234 документа
- Федеральные законы и региональные нормативы
Первый соблазн: взять готовые PDF и скормить их LangChain. Не делайте так. Получите месиво из текста, таблиц, сносок и колонтитулов.
Вместо этого мы написали парсер, который понимает структуру нормативных документов:
def parse_normative_document(pdf_path):
# 1. Извлекаем метаданные: номер, дата, статус
metadata = extract_metadata(pdf_path)
# 2. Разбиваем на логические блоки: разделы, подразделы, пункты
# Важно сохранить иерархию!
structure = detect_structure(pdf_content)
# 3. Очищаем от служебной информации
clean_text = remove_headers_footers(pdf_content)
# 4. Особый случай: таблицы и формулы
# Конвертируем в Markdown с сохранением смысла
tables = extract_tables_to_markdown(pdf_content)
return {
'metadata': metadata,
'structure': structure,
'content': clean_text,
'tables': tables
}
Самая сложная часть - таблицы. В нормах часто пишут: "Расстояние должно быть не менее значений, указанных в таблице 5.1". Если таблицу потерять - ответ будет неполным.
Ошибка №1: разбивать документы на равные куски по 1000 символов. В результате пункт 5.1 оказывается в одном чанке, а таблица 5.1 - в другом. При поиске система найдет только половину информации.
Мы разбивали по логическим границам: раздел → подраздел → пункт. Если пункт большой - делили на абзацы, но никогда не разрывали связь между текстом и таблицей.
2 Векторизация: как сделать так, чтобы поиск понимал "санузел" и "туалет"
Здесь многие используют OpenAI embeddings. Не советую по двум причинам: цена и задержки. Вместо этого - открытые модели.
На февраль 2026 года лучший выбор для русского языка - sbert_large_nlu_ru от DeepPavlov. Модель понимает синонимы и профессиональную лексику.
Но есть нюанс: строительная терминология специфична. "Объект капитального строительства" и "ОКС" - одно и то же для профессионала, но не для общей модели.
Решение: дообучение на доменных данных. Мы взяли 5000 пар "термин-синоним" из строительного глоссария и дообучили модель:
from sentence_transformers import SentenceTransformer, losses
import torch
# Загружаем базовую модель
model = SentenceTransformer('sbert_large_nlu_ru')
# Готовим данные для контрастивного обучения
train_examples = []
for term, synonym in construction_glossary:
# Положительная пара: термин и его синоним
train_examples.append(InputExample(
texts=[term, synonym],
label=1.0
))
# Отрицательная пара: термин и случайное слово
train_examples.append(InputExample(
texts=[term, random_unrelated_term],
label=0.0
))
# Обучаем
train_loss = losses.CosineSimilarityLoss(model)
model.fit(train_objectives=[(train_dataloader, train_loss)])
После дообучения качество поиска выросло на 34% по метрике NDCG@10.
Для векторной базы выбрали Qdrant. Почему не Pinecone или Weaviate? Qdrant работает локально, имеет хорошую поддержку фильтров по метаданным, и это российский продукт (важно для госсектора).
3 Выбор и настройка LLM: какая модель меньше всего врет
Здесь тестировали несколько вариантов:
| Модель | Точность | Склонность к галлюцинациям | Стоимость/производительность |
|---|---|---|---|
| GPT-4.5 Turbo | 92% | Низкая (но есть) | Дорого, 2-3 сек |
| Claude 3.7 Sonnet | 94% | Очень низкая | Дорого, 1-2 сек |
| YandexGPT 3.0 Pro | 89% | Средняя | Средне, 1 сек |
| GigaChat 3.0 | 87% | Высокая | Дешево, 2 сек |
| DeepSeek-R1 (локально) | 85% | Низкая | Бесплатно, 5-7 сек |
Выбрали Claude 3.7 Sonnet. Почему? У Anthropic сделали прорыв в снижении галлюцинаций. Модель буквально "боится" сказать то, чего нет в контексте.
Но даже с Claude нужен правильный промпт. Не такой:
Ты помощник по строительным нормам. Ответь на вопрос.
А такой:
Ты - система обработки нормативных документов. Твоя задача - ответить на вопрос пользователя, используя ТОЛЬКО предоставленные ниже фрагменты документов.
ПРАВИЛА:
1. Если ответа нет в документах - скажи "В предоставленных документах нет информации по этому вопросу"
2. Не добавляй информацию из своих знаний
3. Цитируй документы дословно в кавычках-ёлочках
4. Указывай источник каждого факта: [Документ, раздел, пункт]
Документы:
{context}
Вопрос: {question}
Разница принципиальная. Первый промпт оставляет модели пространство для "творчества". Второй - жёстко ограничивает.
4 Поиск и реранкинг: как найти не только релевантное, но и правильное
Базовая схема RAG (Retrieval-Augmented Generation) часто даёт сбои. Проблема: векторный поиск находит семантически близкие документы, но они могут быть устаревшими или отменёнными.
Пример: пользователь спрашивает про требования к пожарной безопасности. Система находит:
- СП 1.13130.2020 (актуальный)
- СНиП 21-01-97* (частично действующий)
- ВСН 01-87 (отменён в 2005 году)
Если просто отдать всё это модели - она запутается. Нужен реранкинг с учётом:
- Актуальности документа (статус: действует/отменён)
- Юридической силы (ГОСТ Р выше, чем рекомендации)
- Релевантности конкретному запросу
Мы использовали Cohere Rerank v3 (на февраль 2026 это всё ещё лучшая модель для реранкинга). После векторного поиска получаем 20 документов, затем реранкер выбирает топ-5 самых релевантных и актуальных.
Архитектура системы в продакшене
Стек технологий, который работает в реальном проекте:
- Бэкенд: FastAPI + Python 3.11
- Векторная БД: Qdrant в Kubernetes
- LLM: Claude 3.7 Sonnet через API
- Эмбеддинги: sbert_large_nlu_ru (дообученная) на GPU
- Кэш: Redis для кэширования частых запросов
- Мониторинг: Prometheus + Grafana + кастомные метрики качества ответов
Самая важная часть - мониторинг. Мы отслеживаем:
- Процент ответов "информации нет в документах" (должен быть 5-15%)
- Средняя длина цитат в ответах (показатель точности)
- Количество жалоб пользователей на неточности
- Время от запроса до ответа (SLA: 3 секунды)
Типичные ошибки, которые мы совершили (чтобы вы их не повторили)
Ошибка 1: Использовать общую модель эмбеддингов без дообучения. Результат: система не понимала, что "лифтовая шахта" и "шахта лифта" - одно и то же.
Ошибка 2: Не учитывать иерархию документов. Когда в ответе смешиваются федеральные нормы и региональные дополнения без указания приоритета - пользователь теряется.
Ошибка 3: Экономить на реранкинге. Без него в топ попадают устаревшие документы, потому что они часто короче и "точнее" матчатся по запросу.
Ошибка 4: Доверять модели без человеческой проверки. Первые 1000 ответов проверяли вручную. Нашли систематическую ошибку: модель путала "не менее" и "не более" в 3% случаев. Добавили пост-обработку для таких конструкций.
Что в итоге получилось
«Цифровой стандарт» работает в 12 строительных компаниях. За 6 месяцев:
- Точность ответов: 96.7% (проверено экспертами)
- Галлюцинации: 0.3% (в основном в очень сложных составных запросах)
- Среднее время ответа: 2.1 секунды
- Экономия времени инженеров: 8-12 часов в неделю на поиск норм
Система не идеальна. Есть вопросы, на которые она не может ответить (нужны расчёты, нужны чертежи). Но там, где нужно найти норму - она работает лучше человека.
Ключевой урок: чтобы победить галлюцинации, нужно не улучшать модель, а менять архитектуру. Модель должна быть не источником знаний, а их обработчиком.
Если делаете подобную систему для другой отрасли (медицина, юриспруденция, финансы) - берите эту архитектуру за основу. Работает.
P.S. Интересный побочный эффект: когда инженеры видят, что каждый ответ содержит точные цитаты из документов - они начинают больше доверять системе. А доверие - это главная валюта в эпоху, когда всё можно подделать. Это тот случай, когда прозрачность алгоритма становится конкурентным преимуществом.