AI используется всё чаще Кому‑то это упрощает ежедневную рутину, кому‑то заменяет психолога, кому‑то помогает приобретать новые знания. Есть и те, кто хочет существенно усовершенствовать процессы в уже работающем бизнесе или создает на основе AI свои продукты (наш вариант — последний).

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

Данная серия статей про результаты такого тестирования — от простого до самого продвинутого.


Начали с самого очевидного — взяли 18 наиболее популярных AI‑моделей и прогнали их через список из 30 вопросов (по 3 вопроса в 10 разных категориях).

Получив ответы, мы стали думать, как по каким критериям лучше анализировать этот массив информации. Для этого сначала пришлось ответить на вопрос: «А кто, по нашему мнению, является пользователем AI чат‑бота?»

По результатам ответа на вопрос было составлено описание пользователя:

человек, который хочет получить релевантный, понятный, быстрый, краткий и полный ответ на интересующий вопрос.

Иллюстрация нерелевантного ответа
Иллюстрация нерелевантного ответа

Релевантность — соответствие ответа заданному вопросу.

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

Иллюстрация полного ответа
Иллюстрация полного ответа

Полнота — насколько ответ был исчерпывающим.

То есть, должны быть учтены все особенности предмета вопроса (указаны все необходимые для игры характеристики персонажа RPG, уточнения относительно вопроса и т. д.) Например, указано определение Квантовой физики, основные положения указаны полностью.

Иллюстрация непонятного ответа
Иллюстрация непонятного ответа

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

Иллюстрация долгого ожидания ответа
Иллюстрация долгого ожидания ответа

Быстрота — скорость получения ответа от AI‑модели. Была поставлена планка для начала получения ответа до 5 секунд с момента отправки вопроса.

Иллюстрация слишком длинного ответа
Иллюстрация слишком длинного ответа

Краткость — длина ответа для вопросов, не требующих детальных пояснений, в идеале не должна превышать 1000–1100 символов (примерно столько символов содержалось в одной странице текста в веб‑версии AI‑модели).

для вопросов, требующих детальных пояснений, длина ответа была увеличена примерно в 1,5 раза, то есть 2500 символов.

Идея в том, что пользователь вряд ли станет читать огромные полотна текста при поиске ответа на свой вопрос. Если он не найдет что‑то полезное или интересное в первых 2–3 абзацах, то, многовероятно, просто закроет или свернет окно и пойдет искать ответ в других источниках.

Именно эти 5 характеристик стали критерием оценки ответов AI.

На весь процесс с нахождением испытуемых AI‑продуктов, генерацией вопросов, определением критериев оценки и подведением итогов ушло порядка недели.

По результатам исследования были выявлены следующие недостатки в ответах:

  • вопрос с просьбой привести несколько предложений на иностранном языке для помощи в его изучении, а ответ состоит только из предложений на иностранном языке — нет перевода на язык, на котором задавался вопрос;

  • вопрос о создании диалога на китайском языке, а в ответе вместо диалога на китайском языке в виде китайской письменности представлен только пиньинь (запись китайских слов на латинице) — не приведен текст на языке, на котором была просьба создать предложения;

  • вопрос о создании стихотворения в стиле конкретного поэта на определенную тему — ответ не читается ни как стихотворение, ни как что‑то сделанное в стилистике автора;

  • вопрос о создании стихотворения в стиле конкретного поэта на определенную тему — ответ не читается, как стихотворение;

  • вопрос о приведении 5 примеров для вечеринки в стиле 80-х — в ответе приведено по одной идее для 5 разных вечеринок;

  • вопрос о создании загадки для квиза — вместо одной загадки представлено несколько (если быть точным, то 5. Вероятно, здесь имело место некорректное использование истории сообщений при ответе на вопрос);

  • вопрос о советах по поводу улучшения резюме — представлены описание и образец резюме без каких‑то советов;

  • вопрос о создании эссе на определенную тему — ответ не представляет собой эссе;

  • ожидание ответов более 5 секунд;

  • неполные ответы (указаны не все основные положения теории большого взрыва; не разъяснены основные принципы работы солнечных батарей и так далее);

  • по тексту невозможно определить, насколько полным был ответ (сбой в переводе на русский язык, почти весь ответ на иностранном языке или просто в специальных символах)

  • слишком длинные ответы на вопрос, не требующий детальных разъяснений;

  • слишком длинные ответы на вопрос, требующий детальных разъяснений;

  • ответ частично на отличном от вопроса языке (вставки английского, французского и других языков без перевода и разъяснения значения) без каких‑то пояснений;

  • неверный перевод с иностранного языка. Например, перевод должности сервировщика в диалоге как «сервер» (затрудняет чтение и понимание текста);

  • несогласованность диалогов на иностранном языке и языке, на котором был задан вопрос (сначала указан диалог только на китайском, потом диалог только на русском. сложно понять, каким строкам диалога принадлежит перевод);

  • проблема с использованием падежей, склонений, рифм;

  • ошибка с математическими вычислениями. AI считает, что 36 и 1066 чем‑то схожи;

  • внезапные обрывы ответов;

  • сложная для восприятия структура ответа (на просьбу дать советы по улучшению резюме сначала указан образец резюме и только в конце советы по улучшению);

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

Плюс ручного тестирования в том, что тебе не нужно самому себе объяснять, что означают критерии оценки модели и как выявлять отклонения от таких критериев.

Проблемы ручного тестирования AI очевидны:

  • слишком большое время на проверку ответов всех AI‑продуктов (порядка 500 ответов от моделей, каждый из которых необходимо проверить по 5 выбранным критериям);

  • возможность пропуска каких‑то дефектов из‑за невнимательности;

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

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

Сначала мы попытались автоматизировать проверку по ранее сформированным критериям.

Для автоматизации мы решили использовать две AI‑модели:

gpt-4o решала задачу определения релевантности ответа. В инструкциях попросили написать в ответе, является ли переданный текст релевантным ответом на поставленный вопрос и перечислили сформированные нами критерии релевантности. В ответе должно было возвращаться либо «соответствует», либо «нерелевантный ответ». По итогам тестирования работы такой метрики ложноположительных или ложноотрицательных ответов замечено не было. На проверку ответов на вопросы по всем AI‑продуктам (около 500 ответов) было затрачено примерно 1,5$.

import openai
from openai import OpenAI


def check_relevance(question, answer):
    client = OpenAI()
    response=client.chat.completions.create(
    model="gpt-4o",
    messages=[
    {"role": "system", "content": f"""Проверь ответ на вопрос на предмет соответствия 
                        контексту. Например, если задается вопрос на разъяснение 
                        какого-то термина, то для соответствия контексту в ответе 
                        должно быть определение термина и разъясненние основных его 
                        положений. Если вопрос содержит просьбу помочь с чем-то, то 
                        ответ должен обязательно содержать советы или пожелания, 
                        возможно, алгоритм, как решить проблему, указанную в вопросе.
                        Например, если в вопросе будет просьба помочь написать доклад,
                        то в ответе должны обязательно содержаться советы, как успешно
                        написать такой доклад.
                        если в вопросе просьба улучшить что-то, то в ответе должны быть
                        предложены советы и способы для улучшения предмета вопроса.
                        Если вопрос содержит просьбу написать какое-то произведение, 
                        то ответ должен соответствовать загаданному произведению.
                        Обращай внимание на количество загаданного. Например, если в 
                        вопросе будет просьба написать 5 загадок, то в ответе должно 
                        быть 5 загадок.
                        Если в вопросе будет просьба придумать 1 историю, то в ответе 
                        должна быть 1 история.
                        Если ответ полностью соответствует контексту вопроса, то в 
                        ответе возврати "соответствует".
                        В остальных случаях, возвращай "нерелевантный ответ".
                        Вот вопрос: {question}. 
                        Вот ответ: {answer}"""}
    ],
    max_tokens=1000
    )
    content = response.choices[0].message.content
    print(content)
    return content

Для проверки понятности ответа также была привлечена AI‑модель (claude-3–5-sonnet-20 241 022), а в промте описан ожидаемый формат ответа. На все проверки с развернутым ответом, почему именно такая финальная оценка (те же примерные 500 ответов), было затрачено примерно 10$. Пришлось несколько потрудиться с уточнением условий, по которым необходимо проверять ответы, но итоговый результат был вполне себе логичным и обоснованным.

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

Ниже приведен пример проверки ответа на предмет ошибок с использованием падежей, склонений, рифм и т. д.

import anthropic


def check_answer_artifacts(question, answer):
    client = anthropic.Anthropic()
    message = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1000,
        temperature=0,
        system=f"""Ты ассистент, готовый помочь с любым вопросом. 
                        Проверь ответ на вопрос на предмет недочетов в плане 
                        понятности для пользователя. 
                        Недочетами считаются проблемы с использованием падежей, 
                        склонений, возможно, рифм или ритма стихотворений и так далее.
                        Также недочетами считаются наличие символов и знаков, которые 
                        могут быть непонятными для пользователя. Например, сноски без 
                        указания источника или отсутствие разъяснений специальных 
                        терминов.
                        Если ответ не содержит подобных указанным выше недочетов, то в
                        ответе возврати "ответ понятный".
                        В остальных случаях, возвращай "ответ непонятен".
                        Вот ответ: {answer}.
                        Вот вопрос: {question}""",
        messages=[
            {
                "role": "assistant",
                "content": [
                    {
                        "type": "text",
                        "text": """Ожидаемый ответ или дополнительный вопрос от 
                      ассистента"""
                    }
                ]
            }
        ]
    )
    text_blocks = [text_block.text for text_block in message.content 
                   if hasattr(text_block, 'text')]
    message_content = " ".join(text_blocks).strip(': "')  # Убираем лишние символы
    print(message_content)
    return message_content

Для расчета полноты было принято решение использовать BERTScore, а именно параметр F‑score, который учитывает и полноту и точность ответов в расчетах.

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

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

import os
import json
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from completeness.compare_embeddings import calculate_embedding_similarity
from completeness.compare_texts import compare_texts
from google_sheets_info import *
from read_file import read_response_from_file


def test_completeness(questions_dict):
    # Проход по вопросам и расчет показателей полноты
    for question_key, question_info in questions_dict.items():
        question_text = question_info[0]
        folder_path = question_info[1]
        question_row = worksheet.find(question_text).row
        relevance_row = question_row + 1
        clarity_row = question_row + 4
        # Извлечение наименований моделей
        model_names = worksheet.row_values(1)[1:]
        # Извлечение значений показателей Relevance и Clarity с заменой запятых 
        # на точки
        relevance_scores = [value.replace(',', '.') 
                            for value in worksheet.row_values(relevance_row)[1:]]
        clarity_scores = [value.replace(',', '.') 
                          for value in worksheet.row_values(clarity_row)[1:]]
        
        # Сумма значений Relevance и Clarity с учетом наименования моделей
        total_scores = []
        for i in range(len(relevance_scores)):
            if relevance_scores[i] and clarity_scores[i]:  # Проверка на пустоту в 
                                                           # ячейке
                total_scores.append((float(relevance_scores[i]) + 
                                     float(clarity_scores[i]), model_names[i]))
        max_score = max(total_scores, key=lambda x: x[0])
        max_score_value = max_score[0]
        max_score_models = [model for score, model in total_scores 
                            if score == max_score_value]
        
        # Определение идеального ответа на основании рассчитанных 
        # показателей релевантности и понятности
        # Если максимальное значение одно
        if len(max_score_models) == 1:
            gold_answer_file = os.path.join(folder_path, max_score_models[0] + '.txt')
            gold_answer = open(gold_answer_file, 'r', encoding='utf-8').read()
        else:
            # Если несколько максимальных значений, выбираем по лучшему f_score
            max_answers = [open(os.path.join(folder_path, model + '.txt'), 'r', 
                                encoding='utf-8').read() for model in max_score_models]
            best_f_score = 0
            best_answer = None
            best_model_name = None
            for i in range(len(max_answers)):
                for j in range(i + 1, len(max_answers)):
                    f_score = compare_texts(max_answers[i], max_answers[j])
                    if f_score > best_f_score:
                        best_f_score = f_score
                        best_answer = max_answers[i]
                        best_model_name = max_score_models[i]
            gold_answer = best_answer

        # Получение списка файлов ответов
        answer_files = [f for f in os.listdir(folder_path) if f.endswith('.txt')]
        completeness_scores = []
        # Расчет показателя полноты для всех ответов
        for answer_file in answer_files:
            model_answer = open(os.path.join(folder_path, answer_file), 'r', 
                                encoding='utf-8').read()
            completeness_score = calculate_embedding_similarity(gold_answer, 
                                                                model_answer)
            completeness_scores.append((completeness_score, answer_file[:-4])) 

        # Запись значений в таблицу Google Sheets
        completeness_row = question_row + 2
        worksheet.update_cell(completeness_row, 1, "Completeness")
        for score, model_name in completeness_scores:
            col_index = model_names.index(model_name) + 2 # +2, так как первые 2 
                                                          #столбца - Question и 
                                                          #Relevance
            worksheet.update_cell(completeness_row, col_index, score)
    print("Скрипт успешно выполнен.")

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

Пример записи результатов расчета по выбранным метрикам в Google Sheets:
Пример записи результатов расчета по выбранным метрикам в Google Sheets:

Плюсы автоматизации тестирования AI:

  • существенное снижение времени на оценку ответов;

  • возможность масштабирования на более широкий пул вопросов или выборку AI‑продуктов;

Минусы автоматизации (по выбранным критериям):

  • критерии не поддаются автоматизации с помощью обычных функций и методов (по крайней мере, нами такие универсальные методы не были найдены). Как минимум, есть проблемы в оценке творческих задач. Как определить, что все элементы стихотворения в тексте ответа присутствуют? Как определить, что соблюдена стилистика конкретного поэта? Как определить, что настроение произведения соответствует обычному настроению стихов конкретного автора? Или как протестировать релевантность ответа на просьбу создать описание персонажа для RPG‑игры, не имея при себе какого‑то эталона? Теоретически может быть столько релевантных и полных ответов, сколько моделей мы выбрали для тестирования. При этом по выбору способа формирования все такие ответы могут быть разными. Таким образом, к решению проблемы определения релевантности и полноты ответа для творческих задач не подходит ни BERTScore, ни AI, поскольку мы не можем поручиться за верность интерпретации текста, полученного, например, в ответе на задание «напиши стихотворение о зиме в стиле Сергея Есенина».
    До сих пор какого‑то адекватного решения нами не найдено, поскольку проблема связана с огромным количеством критериев оценки, для проверки которых, разве что, надо создавать собственную модель, проверяющую создание такого творческого произведения как со стороны автора, так и со стороны зрителя (способно ли «творчество» модели вызвать те же или схожие эмоции, что вызывают произведения автора?). Задача представляется довольно трудной. С другой стороны, при нынешних объемах данных, на которых обучаются модели, совсем невыполнимой ее тоже назвать нельзя.

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

  • наконец, использование AI как способа тестирования ответов моделей также сопряжено с трудностями. AI требует максимально детального описания того, как должен оцениваться текст по какому‑то критерию. При этом должен быть соблюден баланс детализации и краткости инструкций. И даже идеально прописанные инструкции по оценке не могут нас застраховать от выдачи ложноположительных и ложноотрицательных результатов.

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

Вот с такими выводами мы решили искать новые пути к решению задачи автоматизации оценки качества ответов моделей на поставленные задачи или заданные вопросы.

Как говорится, когда понимаешь, что зашел в тупик, просто вернись к началу.

Что мы и сделали.

Комментарии (0)