Автоматизация создания Дополнительных Соглашений (ДС) с помощью локальной модели Qwen
В этой статье я расскажу о разработке решения для автоматической генерации Дополнительных Соглашений (ДС) к договорам. Основная задача — избавить юристов и менеджеров от рутины, переложив анализ текста договора и формирование «рыбы» документа на искусственный интеллект.
В качестве «мозга» системы была выбрана локальная языковая модель Qwen (в частности версия qwen3-vl-30b-a3b-thinking), работающая через локальный API-сервер. Это обеспечивает конфиденциальность данных (тексты договоров не покидают контур компании) и отсутствие затрат на облачные токены.
Архитектура решения
Система написана на Python и состоит из трех основных этапов:
- Сбор данных: Загрузка исходных данных о договорах из базы SQLite.
- Интеллектуальный анализ (LLM): Извлечение ключевых параметров (стороны, номера, даты) и логический вывод новых данных (следующий номер пункта, склонение ФИО).
- Генерация документа: Заполнение шаблона
.docxполученными данными.
1. Строгая структура данных (JSON Schema)
Одной из главных проблем при работе с LLM является нестабильность вывода. Чтобы модель возвращала данные в четко заданном формате, я использовал Structured Outputs (JSON Schema).
В коде определена схема ADDENDUM_SCHEMA, которая жестко диктует модели, какие поля она должна вернуть:
номер_ДС,дата_ДСподписант_заказчика_в_родительном падеже(критично для преамбулы ДС)- Блоки для разделов «Предмет», «Оплата», «Сроки» (тип единицы, номер пункта, текст цитаты).
Это позволяет избежать парсинга свободного текста и сразу получать готовый JSON для вставки в шаблон.
2. Техника «Подсказок» (Structural Hints)
Локальные модели, даже мощные, иногда ошибаются в простой арифметике или навигации по большим текстам (например, могут неправильно определить последний пункт в разделе).
Чтобы повысить точность, я реализовал гибридный подход. Вместо того чтобы просить модель саму считать пункты, я делаю это алгоритмически на Python с помощью функции structural_hints_for_llm:
- Скрипт парсит структуру договора (главы, статьи).
- Находит разделы, содержащие ключевые слова («ПРЕДМЕТ», «ОПЛАТА», «СРОК»).
- Вычисляет последний номер пункта (например,
2.4) и генерирует номер для нового пункта (2.5).
Эти вычисленные данные передаются модели в поле hints. Модели остается лишь «собрать» всё в красивую фразу, например: “дополнить раздел 2 пунктом 2.5 следующего содержания…”.
Пример кода подсказок:
def structural_hints_for_llm(contract_json: dict) -> dict:
# ... логика поиска разделов ...
subj = find(lambda tt: re.search(r"ПРЕДМЕТ", tt, re.IGNORECASE))
if subj:
out["тип_единицы_предмет"] = subj["type"]
out["последний_пункт_предмет"] = subj["last"]
out["добавляемый_пункт_предмет"] = subj["next"] # Python сам посчитал +1
return out 3. Работа с русской грамматикой
Для корректного формирования ДС необходимо склонять имена и должности (например, “в лице Генерального директора Иванова…”). В промпте для LLM я использую специальную инструкцию:
“Верни грамматически корректные фразы… а также должность и ФИО подписантов в родительном падеже… ВНИМАНИЕ: поля родительного падежа возвращай БЕЗ предлога ‘в лице’, только ‘<должность> <ФИО>’“.
Дополнительно на стороне Python реализована функция очистки sanitize_signatory_gen, которая убирает лишние скобки и мусор, если модель всё-таки добавила их.
4. Взаимодействие с API
Для общения с моделью используется стандартный REST API (совместимый с OpenAI), поднятый локально (например, через LM Studio на порту 1234).