Используем LLM для подбора подрядчиков: как это работает

Привет, Хабр! Меня зовут Иван, работаю data scientist в Doubletapp. Хочу поделиться кейсом, как мы решали задачу по автоматизации процессов отсмотра, сортировки и сверки входящих документов заказчика. 

8d35965665ebed80c67ec07659688f5a.jpg

Мы работали с организацией, которая регулярно проводит тендеры. Победители тендеров должны обладать набором конкретных компетенций (образование сотрудников, парк оборудования, подтвержденный опыт и т. д.), чтобы обеспечить качественное и безопасное оказание услуг. Поэтому приходится тщательно изучать документы претендентов на этапе подачи: все ли данные там содержатся и соответствуют ли они требованиям. Ранее этим занимались люди, на отсмотр большого объема входящей документации они тратили много времени и допускали ошибки. Чтобы повысить эффективность процедуры отбора и сократить время на принятие решения, была построена система, использующая большую языковую модель Mistral-7B-v0.2, в разработке которой я участвовал. 

Читайте в статье:

 С какими документами мы работали и что в них должно быть
 Классификация и сверка документов
 Как система показала себя в работе

С какими документами мы работали и что в них должно быть

Расскажу подробнее, в чем состояла задача. 

Мы получили набор документов, предоставленный участником отбора, а также набор критериев для его оценки. Критерий может быть либо подтверждён, либо не подтвержден имеющимися документами, причём по каждому из критериев было заранее задано, какие документы могут служить подтверждением. 

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

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

Классификация и сверка документов

Из-за специфики, упомянутой выше, процесс проверки участника на соответствие критерию был реализован в два этапа.

Классификация

На первом требовалось отсеять документы, не релевантные для данного критерия. Например, при проверке критерия про опыт, убрать списки транспортных средств, договоры о проведении лабораторных исследований и т. д. Для этого на основе LLM был реализован бинарный классификатор, который паре (критерий, документ) ставит в соответствие метку 0 или 1, где 0 означает, что данный документ не подходит для подтверждения данного критерия, 1 — что подходит.

Для классификации используется следующий промпт:

"""
	Ты специалист по подбору подрядчиков для оказания услуг следующего типа: {contract_type}
	Тебе будет дано условие, которому должен удовлетворять потенциальный исполнитель и предоставленный им документ.	
Может ли документ служить подтверждением того, что исполнитель соответствует условию?
	Приведи краткое рассуждение. Только после рассуждения предоставь ответ в формате [ответ].
	Например, [1], если документ может подтвердить выполнение условия, или [0] в противном случае.
	Пиши ответ ТОЛЬКО В САМОМ КОНЦЕ и только в формате
	[0] или [1].
        
	Условие: {criterion}
	Документ: {document}
 """

где criterion — формулировка критерия оценки исполнителя,  document — собственно сам документ, предоставленный исполнителем.

Просьба привести рассуждение прежде чем выдавать ответ обусловлена тем, что decoder-only модели, к которым относится и Mistral, генерируют каждый следующий токен ответа, опираясь как на входные данные, так и на уже сгенерированную часть собственного ответа. Таким образом, имея возможность видеть собственные рассуждения, предшествующие выводу, модель принимает более обоснованное решение.

Дополнительно в качестве входных данных был введён contract_type, который определяет, какие именно услуги или работы предполагается выполнять. В данном случае, в contract_type всегда передавалось «Услуги по проектированию мостов». Это позволило корректно проверять критерий про наличие у исполнителя опыта работы, поскольку сам критерий формулировался так: «Наличие опыта оказания услуг по предмету отбора».

Изначально модель ничего не знала о предмете отбора, поэтому документы, в действительности не относящиеся к данному критерию, помечала как релевантные. Например, если на входе был договор об установке POS-систем и не было этого дополнительного контекста contract_type, то модель делала вывод, что проверяется опыт исполнителя в установке POS-систем, и отвечала 1. Менять исходную формулировку критерия, чтобы в ней уточнялся вид услуг, было нежелательно, поскольку в дальнейшем планировалось использовать систему для подбора исполнителей и на другие виды подрядов с одним и тем же набором критериев, без необходимости редактировать их.

Кроме того, исходные документы предварительно проходили суммаризацию, и в классификатор попадали уже их «краткие содержания». Обусловлено это было размером контекстного окна модели Mistral-Instruct-v0.1, которая использовалась изначально. Позже, после перехода на Mistral более новой версии с бо́льшим контекстным окном, от суммаризации отказались, поскольку часто данные, необходимые модели для принятия решения, после неё терялись.

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

accuracy

precision

recall

F1

0.79

0.90

0.82

0.86

Для расчета метрик использовалась разметка, сформированная экспертом заказчика при ручной оценке исполнителей в предыдущих тендерах. Для всех участников отбора каждому критерию был поставлен в соответствие список номеров документов, относящихся к данному критерию.

Сверка

После того, как получен отфильтрованный список документов после классификатора, производится сверка документов между собой. Для этого необходимо все документы разом подать в LLM с запросом на формирование окончательного ответа, достаточно ли данных документов для подтверждения критерия.

Предположим, что нужно проверить наличие в штате компании-участника инженера по проектированию мостов. В соответствии с процедурой оценки, используемой заказчиком, необходимо проверить наличие приказа о назначении сотрудника на должность, а также наличие диплома, подтверждающего квалификацию этого сотрудника как инженера по проектированию мостов. Может возникнуть ситуация, когда и приказ, и диплом имеются, но относятся к разным сотрудникам. При отсутствии других документов этого будет недостаточно для подтверждения критерия. Именно для таких ситуаций было решено дать LLM видеть все документы в совокупности, с расчётом на то, что она обнаружит расхождения в ключевых сведениях, содержащихся в документах (таких как ФИО сотрудника/выпускника).

Вместо того, чтобы подавать в LLM документы целиком (или в суммаризованном виде), было решено выделить из каждого документа сами ключевые характеристики, по которым и требовалось произвести сравнение. Для каждого критерия был заранее определён перечень сведений для извлечения (здесь представлена только его часть):

{
   "0" : [
       "Наименование документа (договор, акт, техзадание, либо ничего из перечисленного)",
       "Контрагенты (заказчик, исполнитель",
       "Место оказания услуг",
       "Даты оказания услуг"
   ],
   "2" : [
       "Наименование документа (ПТС, СТС, договор купли-продажи или лизинга, либо ничего из перечисленного",
       "Тип транспортного средства",
       "Срок эксплуатации транспортного средства",
       "Категория транспортного средства"
   ],
   "5" : [
       "Наименование документа (договор, акт, либо ничего из перечисленного)",
       "Контрагенты (заказчик, исполнитель договора на проведение медосмотра",
       "Если документ - акт, подписан ли он главным врачом лечебного учреждения"
   ]
}

Далее для извлечения этих метаданных на каждом из документов строился RAG со следующим промптом.

Подробнее о RAG читайте в статье.

prompt_template = """
   Извлеки из документа требуемые сведения. Отвечай максимально коротко.
   Если нужные сведения не указаны в документе, отвечай None.
   В ответе пиши только требуемые сведения и ничего более.
   Ответ выводи только в квадратных скобках.


   Сведения: {meta}
   Документ: {document}
"""

Здесь input meta означает наименование сведения из перечня выше (например, «Категория транспортного средства» или «Место оказания услуг»). В document передается чанк документа, найденный векторным поиском. При поиске запросом было то же meta. Векторный поиск осуществлялся по косинусной близости векторных представлений, полученных с помощью модели e5-base.

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

metas = [
	[«Диплом», «Иванов Иван Иванович», «Инженер по проектированию мостов»],
	[«Приказ», «Иванов Иван Иванович», «Инженер по проектированию мостов»],
],

который затем передавался LLM для принятия итогового решения о соответствии либо несоответствии участника критерию:

prompt_template = """
   Ты специалист по отбору подрядчиков для выполнения работ/оказания услуг.
   Критерий отбора:
   {condition}.
   Для подтверждения критерия требуется следующий пабор документов:
   {confirming_docs}


   Участник отбора предоставил следующие документы:
   {metas}


   Отвечай [1], если предоставленные документы подтверждают критерий отбора.
   В этом случае выведи также номера подтверждающих документов.
   В противном случае, отвечай [0].
   В этом случае, дай очень краткое объяснения, чего не хватает участнику отбора для подтверждения критерия.
"""

Здесь condition — то же самое, что criterion в промпте для классификатора, а confirming_docs — наименования документов, которые, согласно процедуре проверки, могут подтверждать данный критерий.

Как система показала себя в работе

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

Здесь важно было оценить, насколько хорошо система отсеивает документы без «пары» (например, договоры об оказании услуг без актов или дипломы сотрудников без приказов о назначении на должность). Поэтому каждому критерию был поставлен в соответствие тот же набор документов, что и в разметке для классификатора, за вычетом таких беспарных документов.

Результат оценки показал высокую эффективность системы по большинству из критериев, на которых был получен F1 ~0.82.

Исключение составили три критерия с F-мерой ~0.5: критерий о наличии опыта оказания услуг, о наличии транспортных средств и о наличии лабораторного контроля за соблюдением санитарных норм.

Анализ выходных данных дал понять, что имеются проблемы в извлечении метаданных из документов, наиболее выраженные для этих трех критериев. Вероятная причина — не лучшим образом сформулированные meta (которые передаются в промпт LLM для извлечения метаданных, а также используются в векторном поиске в качестве запроса), из-за которых часть документа, содержащая требуемые данные, находится при поиске не в top1.

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

Заключение

Итак, для автоматизации бизнес-процессов мы разработали систему, использующую большую языковую модель Mistral-7B-v0.2, и в статье я описал, как она работает, как мы решали конкретные проблемы, а также перспективы ее совершенствования. Если у вас есть подобный опыт, давайте обсудим в комментариях, с какими трудностями вы сталкивались при автоматизации рабочих процессов и какие перспективы видите в применении больших языковых моделей в этой области. Отвечу на вопросы в комментариях.

© Habrahabr.ru