Your AI Product Needs Evals
Хамель Хусейн, независимый консультант (ранее руководивший командой CodeSearchNet, предшественника GitHub Copilot), утверждает, что главная причина провала LLM-продуктов — отсутствие надёжных систем оценки (evals). Успех зависит от скорости итераций, которая опирается на три процесса: оценку качества, отладку и изменение поведения системы. На примере Lucy — ИИ-ассистента риелторской SaaS-платформы Rechat — описаны три уровня оценки: юнит-тесты (Level 1, у Rechat их сотни), оценка человеком и моделью с логированием трейсов через LangSmith (Level 2) и A/B-тестирование (Level 3). Автор подчёркивает необходимость постоянно смотреть на данные, строить собственные инструменты просмотра, использовать LLM для генерации тестов и синтетических данных, а также измерять precision и recall при согласовании модели-судьи с человеком. Готовая система оценки бесплатно открывает возможности fine-tuning и быстрой отладки, создавая маховик для стремительных итераций.
Motivation
Мотивация
I started working with language models five years ago when I led the team that created CodeSearchNet, a precursor to GitHub CoPilot. Since then, I’ve seen many successful and unsuccessful approaches to building LLM products. I’ve found that unsuccessful products almost always share a common root cause: a failure to create robust evaluation systems.
Я начал работать с языковыми моделями пять лет назад, когда возглавлял команду, создавшую CodeSearchNet — предшественника GitHub CoPilot. С тех пор я видел множество успешных и неудачных подходов к созданию LLM-продуктов. Я обнаружил, что у неудачных продуктов почти всегда есть общая первопричина: неспособность создать надёжные системы оценки.
I’m currently an independent consultant who helps companies build domain-specific AI products. I hope companies can save thousands of dollars in consulting fees by reading this post carefully. As much as I love making money, I hate seeing folks make the same mistake repeatedly.
Сейчас я независимый консультант, помогающий компаниям создавать предметно-ориентированные ИИ-продукты. Надеюсь, что, внимательно прочитав этот пост, компании смогут сэкономить тысячи долларов на консалтинговых услугах. Как бы я ни любил зарабатывать деньги, мне ненавистно видеть, как люди раз за разом совершают одну и ту же ошибку.
This post outlines my thoughts on building evaluation systems for LLMs-powered AI products.
В этом посте я излагаю свои мысли о построении систем оценки для ИИ-продуктов на базе LLM.
Iterating Quickly == Success
Быстрые итерации == Успех
Like software engineering, success with AI hinges on how fast you can iterate. You must have processes and tools for:
Как и в разработке ПО, успех в ИИ зависит от того, насколько быстро вы можете итерировать. У вас должны быть процессы и инструменты для:
Оценки качества (напр.: тесты). Отладки проблем (напр.: логирование и просмотр данных). Изменения поведения или системы (промпт-инжиниринг, fine-tuning, написание кода)
Many people focus exclusively on #3 above, which prevents them from improving their LLM products beyond a demo.1 Doing all three activities well creates a virtuous cycle differentiating great from mediocre AI products (see the diagram below for a visualization of this cycle).
Многие фокусируются исключительно на пункте №3 выше, что мешает им вывести свои LLM-продукты дальше уровня демо.1 Качественное выполнение всех трёх видов деятельности создаёт благотворный цикл, отличающий отличные ИИ-продукты от посредственных (визуализацию этого цикла см. на диаграмме ниже).
If you streamline your evaluation process, all other activities become easy. This is very similar to how tests in software engineering pay massive dividends in the long term despite requiring up-front investment.
Если вы оптимизируете процесс оценки, все остальные виды деятельности становятся простыми. Это очень похоже на то, как тесты в разработке ПО приносят колоссальную отдачу в долгосрочной перспективе, несмотря на необходимость предварительных вложений.
To ground this post in a real-world situation, I’ll walk through a case study in which we built a system for rapid improvement. I’ll primarily focus on evaluation as that is the most critical component.
Чтобы привязать этот пост к реальной ситуации, я разберу кейс, в котором мы построили систему для быстрого улучшения. В основном я сосредоточусь на оценке, поскольку это наиболее критичный компонент.
Case Study: Lucy, A Real Estate AI Assistant
Кейс: Lucy, ИИ-ассистент для недвижимости
Rechat is a SaaS application that allows real estate professionals to perform various tasks, such as managing contracts, searching for listings, building creative assets, managing appointments, and more. The thesis of Rechat is that you can do everything in one place rather than having to context switch between many different tools.
Rechat — это SaaS-приложение, позволяющее специалистам по недвижимости выполнять различные задачи: управлять договорами, искать объекты, создавать креативные материалы, управлять встречами и многое другое. Идея Rechat в том, что можно делать всё в одном месте, а не переключаться между множеством разных инструментов.
Rechat’s AI assistant, Lucy, is a canonical AI product: a conversational interface that obviates the need to click, type, and navigate the software. During Lucy’s beginning stages, rapid progress was made with prompt engineering. However, as Lucy’s surface area expanded, the performance of the AI plateaued. Symptoms of this were:
ИИ-ассистент Rechat, Lucy — это канонический ИИ-продукт: разговорный интерфейс, избавляющий от необходимости кликать, печатать и перемещаться по ПО. На начальных этапах Lucy быстрый прогресс достигался с помощью промпт-инжиниринга. Однако по мере расширения охвата Lucy производительность ИИ вышла на плато. Симптомами этого были:
Устранение одного режима отказа приводило к появлению других — словно игра в «ударь крота». Видимость эффективности ИИ-системы по разным задачам была ограниченной и не выходила за рамки субъективных «прикидок на ощущение». Промпты разрастались в длинные и громоздкие формы, пытаясь охватить многочисленные крайние случаи и примеры.
Problem: How To Systematically Improve The AI?
Проблема: как систематически улучшать ИИ?
To break through this plateau, we created a systematic approach to improving Lucy centered on evaluation. Our approach is illustrated by the diagram below.
Чтобы пробить это плато, мы создали систематический подход к улучшению Lucy, сосредоточенный на оценке. Наш подход проиллюстрирован на диаграмме ниже.
This diagram is a best-faith effort to illustrate my mental model for improving AI systems. In reality, the process is non-linear and can take on many different forms that may or may not look like this diagram.
Эта диаграмма — добросовестная попытка проиллюстрировать мою ментальную модель улучшения ИИ-систем. В реальности процесс нелинеен и может принимать множество разных форм, которые могут и не походить на эту диаграмму.
I discuss the various components of this system in the context of evaluation below.
Ниже я разбираю различные компоненты этой системы в контексте оценки.
The Types Of Evaluation
Типы оценки
Rigorous and systematic evaluation is the most important part of the whole system. That is why “Eval and Curation” is highlighted in yellow at the center of the diagram. You should spend most of your time making your evaluation more robust and streamlined.
Строгая и систематическая оценка — важнейшая часть всей системы. Именно поэтому «Оценка и курирование» выделены жёлтым в центре диаграммы. Большую часть времени вам следует тратить на то, чтобы сделать вашу оценку более надёжной и оптимизированной.
There are three levels of evaluation to consider:
Стоит рассматривать три уровня оценки:
Уровень 1: Юнит-тесты Уровень 2: Оценка моделью и человеком (включая отладку) Уровень 3: A/B-тестирование
The cost of Level 3 > Level 2 > Level 1. This dictates the cadence and manner you execute them. For example, I often run Level 1 evals on every code change, Level 2 on a set cadence and Level 3 only after significant product changes. It’s also helpful to conquer a good portion of your Level 1 tests before you move into model-based tests, as they require more work and time to execute.
Стоимость Уровня 3 > Уровня 2 > Уровня 1. Это определяет частоту и манеру их выполнения. Например, я часто запускаю оценки Уровня 1 при каждом изменении кода, Уровня 2 — с заданной периодичностью, а Уровня 3 — только после значительных изменений продукта. Также полезно покрыть значительную часть ваших тестов Уровня 1, прежде чем переходить к тестам на основе модели, поскольку последние требуют больше работы и времени на выполнение.
There isn’t a strict formula as to when to introduce each level of testing. You want to balance getting user feedback quickly, managing user perception, and the goals of your AI product. This isn’t too dissimilar from the balancing act you must do for products more generally.
Не существует строгой формулы, когда вводить каждый уровень тестирования. Нужно балансировать между быстрым получением обратной связи от пользователей, управлением восприятием пользователей и целями вашего ИИ-продукта. Это не слишком отличается от того балансирования, которое приходится выполнять для продуктов в целом.
Level 1: Unit Tests
Уровень 1: Юнит-тесты
Unit tests for LLMs are assertions (like you would write in pytest). Unlike typical unit tests, you want to organize these assertions for use in places beyond unit tests, such as data cleaning and automatic retries (using the assertion error to course-correct) during model inference. The important part is that these assertions should run fast and cheaply as you develop your application so that you can run them every time your code changes. If you have trouble thinking of assertions, you should critically examine your traces and failure modes. Also, do not shy away from using an LLM to help you brainstorm assertions!
Юнит-тесты для LLM — это утверждения (assertions), подобные тем, что вы писали бы в pytest. В отличие от типичных юнит-тестов, эти утверждения стоит организовать для использования и за пределами юнит-тестов — например, для очистки данных и автоматических повторных попыток (используя ошибку утверждения для корректировки курса) во время инференса модели. Важно, чтобы эти утверждения выполнялись быстро и дёшево по мере разработки приложения, чтобы вы могли запускать их при каждом изменении кода. Если вам трудно придумать утверждения, стоит критически изучить свои трейсы и режимы отказа. Также не стесняйтесь использовать LLM, чтобы помочь себе в мозговом штурме утверждений!
Step 1: Write Scoped Tests
Шаг 1: Пишите узконаправленные тесты
The most effective way to think about unit tests is to break down the scope of your LLM into features and scenarios. For example, one feature of Lucy is the ability to find real estate listings, which we can break down into scenarios like so:
Наиболее эффективный способ мыслить о юнит-тестах — разбить охват вашего LLM на функции (features) и сценарии. Например, одна из функций Lucy — способность находить объекты недвижимости, которую мы можем разбить на сценарии так:
Feature: Listing Finder
Функция: Поиск объявлений
This feature to be tested is a function call that responds to a user request to find a real estate listing. For example, “Please find listings with more than 3 bedrooms less than $2M in San Jose, CA”
Тестируемая функция — это вызов функции, реагирующий на запрос пользователя найти объявление о недвижимости. Например: «Пожалуйста, найди объявления с более чем 3 спальнями дешевле $2M в Сан-Хосе, Калифорния»
The LLM converts this into a query that gets run against the CRM. The assertion then verifies that the expected number of results is returned. In our test suite, we have three user inputs that trigger each of the scenarios below, which then execute corresponding assertions (this is an oversimplified example for illustrative purposes):
LLM преобразует это в запрос, который выполняется по CRM. Затем утверждение проверяет, что возвращается ожидаемое количество результатов. В нашем наборе тестов есть три пользовательских ввода, которые запускают каждый из сценариев ниже, после чего выполняются соответствующие утверждения (это упрощённый пример для иллюстрации):
There are also generic tests that aren’t specific to any one feature. For example, here is the code for one such generic test that ensures the UUID is not mentioned in the output:
Есть также общие тесты, не привязанные к какой-либо одной функции. Например, вот код одного такого общего теста, который гарантирует, что UUID не упоминается в выводе:
const noExposedUUID = message => {
// Remove all text within double curly braces
const sanitizedComment = message.comment.replace(/\{\{.*?\}\}/g, '')
// Search for exposed UUIDs
const regexp = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/ig
const matches = Array.from(sanitizedComment.matchAll(regexp))
expect(matches.length, 'Exposed UUIDs').to.equal(0, 'Exposed UUIDs found')
}
const noExposedUUID = message => { // Remove all text within double curly braces const sanitizedComment = message.comment.replace(/\{\{.*?\}\}/g, '') // Search for exposed UUIDs const regexp = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/ig const matches = Array.from(sanitizedComment.matchAll(regexp)) expect(matches.length, 'Exposed UUIDs').to.equal(0, 'Exposed UUIDs found') }
CRM results returned to the LLM contain fields that shouldn’t be surfaced to the user; such as the UUID associated with an entry. Our LLM prompt tells the LLM to not include UUIDs. We use a simple regex to assert that the LLM response doesn’t include UUIDs.
Результаты CRM, возвращаемые LLM, содержат поля, которые не должны показываться пользователю — например, UUID, связанный с записью. Наш промпт для LLM указывает модели не включать UUID. Мы используем простое регулярное выражение, чтобы убедиться, что ответ LLM не содержит UUID.
Rechat has hundreds of these unit tests. We continuously update them based on new failures we observe in the data as users challenge the AI or the product evolves. These unit tests are crucial to getting feedback quickly when iterating on your AI system (prompt engineering, improving RAG, etc.). Many people eventually outgrow their unit tests and move on to other levels of evaluation as their product matures, but it is essential not to skip this step!
У Rechat сотни таких юнит-тестов. Мы постоянно обновляем их на основе новых отказов, которые наблюдаем в данных, по мере того как пользователи бросают вызов ИИ или продукт развивается. Эти юнит-тесты крайне важны для быстрого получения обратной связи при итерациях над вашей ИИ-системой (промпт-инжиниринг, улучшение RAG и т. д.). Многие со временем перерастают свои юнит-тесты и переходят к другим уровням оценки по мере зрелости продукта, но крайне важно не пропускать этот шаг!
Step 2: Create Test Cases
Шаг 2: Создавайте тестовые случаи
To test these assertions, you must generate test cases or inputs that will trigger all scenarios you wish to test. I often utilize an LLM to generate these inputs synthetically; for example, here is one such prompt Rechat uses to generate synthetic inputs for a feature that creates and retrieves contacts:
Чтобы протестировать эти утверждения, нужно сгенерировать тестовые случаи или входные данные, которые запустят все сценарии, которые вы хотите проверить. Я часто использую LLM для синтетической генерации таких входов; например, вот один такой промпт, который Rechat применяет для генерации синтетических входов для функции создания и получения контактов:
Write 50 different instructions that a real estate agent can give to his assistant to create contacts on his CRM. The contact details can include name, phone, email, partner name, birthday, tags, company, address and job.
For each of the instructions, you need to generate a second instruction which can be used to look up the created contact.
. The results should be a JSON code block with only one string as the instruction like the following:
[
["Create a contact for John (johndoe@apple.com)",
"What's the email address of John Smith?"]
]
Write 50 different instructions that a real estate agent can give to his assistant to create contacts on his CRM. The contact details can include name, phone, email, partner name, birthday, tags, company, address and job. For each of the instructions, you need to generate a second instruction which can be used to look up the created contact. . The results should be a JSON code block with only one string as the instruction like the following: [ ["Create a contact for John (johndoe@apple.com)", "What's the email address of John Smith?"] ]
Using the above prompt, we generate test cases like below:
С помощью приведённого выше промпта мы генерируем тестовые случаи, как показано ниже:
[
[
'Create a contact for John Smith (johndoe@apple.com) with phone number 123-456-7890 and address 123 Apple St.',
'What\'s the email address of John Smith?'
],
[
'Add Emily Johnson with phone 987-654-3210, email emilyj@email.com, and company ABC Inc.',
'What\'s the phone number for Emily Johnson?'
],
[
'Create a contact for Tom Williams with birthday 10/20/1985, company XYZ Ltd, and job title Manager.',
'What\'s Tom Williams\' job title?'
],
[
'Add a contact for Susan Brown with partner name James Brown, and email susanb@email.com.',
'What\'s the partner name of Susan Brown?'
],
…
]
[ [ 'Create a contact for John Smith (johndoe@apple.com) with phone number 123-456-7890 and address 123 Apple St.', 'What\'s the email address of John Smith?' ], [ 'Add Emily Johnson with phone 987-654-3210, email emilyj@email.com, and company ABC Inc.', 'What\'s the phone number for Emily Johnson?' ], [ 'Create a contact for Tom Williams with birthday 10/20/1985, company XYZ Ltd, and job title Manager.', 'What\'s Tom Williams\' job title?' ], [ 'Add a contact for Susan Brown with partner name James Brown, and email susanb@email.com.', 'What\'s the partner name of Susan Brown?' ], … ]
For each of these test cases, we execute the first user input to create the contact. We then execute the second query to fetch that contact. If the CRM doesn’t return exactly 1 result then we know there was a problem either creating or fetching the contact. We can also run generic assertions like the one to verify UUIDs are not in the response. You must constantly update these tests as you observe data through human evaluation and debugging. The key is to make these as challenging as possible while representing users’ interactions with the system.
Для каждого из этих тестовых случаев мы выполняем первый пользовательский ввод, чтобы создать контакт. Затем выполняем второй запрос, чтобы получить этот контакт. Если CRM возвращает не ровно 1 результат, мы понимаем, что возникла проблема либо при создании, либо при получении контакта. Мы также можем запускать общие утверждения — например, то, что проверяет отсутствие UUID в ответе. Эти тесты нужно постоянно обновлять по мере того, как вы наблюдаете данные через оценку человеком и отладку. Главное — сделать их максимально сложными, но при этом отражающими взаимодействие пользователей с системой.
You don’t need to wait for production data to test your system. You can make educated guesses about how users will use your product and generate synthetic data. You can also let a small set of users use your product and let their usage refine your synthetic data generation strategy. One signal you are writing good tests and assertions is when the model struggles to pass them - these failure modes become problems you can solve with techniques like fine-tuning later on.
Вам не нужно ждать продакшен-данных, чтобы тестировать систему. Вы можете делать обоснованные предположения о том, как пользователи будут использовать ваш продукт, и генерировать синтетические данные. Можно также дать небольшой группе пользователей попользоваться продуктом и позволить их активности уточнить вашу стратегию генерации синтетических данных. Один из признаков того, что вы пишете хорошие тесты и утверждения, — когда модель с трудом их проходит; эти режимы отказа становятся проблемами, которые позже можно решить такими техниками, как fine-tuning.
On a related note, unlike traditional unit tests, you don’t necessarily need a 100% pass rate. Your pass rate is a product decision, depending on the failures you are willing to tolerate.
В связи с этим, в отличие от традиционных юнит-тестов, вам не обязательно нужен 100%-й процент прохождения. Ваш процент прохождения — это продуктовое решение, зависящее от того, какие отказы вы готовы терпеть.
Step 3: Run & Track Your Tests Regularly
Шаг 3: Регулярно запускайте и отслеживайте свои тесты
There are many ways to orchestrate Level 1 tests. Rechat has been leveraging CI infrastructure (e.g., GitHub Actions, GitLab Pipelines, etc.) to execute these tests. However, the tooling for this part of the workflow is nascent and evolving rapidly.
Есть много способов оркестровать тесты Уровня 1. Rechat использует CI-инфраструктуру (напр., GitHub Actions, GitLab Pipelines и т. д.) для выполнения этих тестов. Однако инструментарий для этой части рабочего процесса зарождается и быстро развивается.
My advice is to orchestrate tests that involve the least friction in your tech stack. In addition to tracking tests, you need to track the results of your tests over time so you can see if you are making progress. If you use CI, you should collect metrics along with versions of your tests/prompts outside your CI system for easy analysis and tracking.
Мой совет — оркеструйте тесты с наименьшим трением в вашем технологическом стеке. Помимо отслеживания тестов, нужно отслеживать их результаты во времени, чтобы видеть, прогрессируете ли вы. Если вы используете CI, стоит собирать метрики вместе с версиями ваших тестов/промптов за пределами CI-системы для удобного анализа и отслеживания.
I recommend starting simple and leveraging your existing analytics system to visualize your test results. For example, Rechat uses Metabase to track their LLM test results over time. Below is a screenshot of a dashboard Rechat built with Metabase:
Я рекомендую начинать с простого и использовать вашу существующую аналитическую систему для визуализации результатов тестов. Например, Rechat использует Metabase для отслеживания результатов своих LLM-тестов во времени. Ниже — скриншот дашборда, который Rechat построил с помощью Metabase:
This screenshot shows the prevalence of a particular error (shown in yellow) in Lucy before (left) vs after (right) we addressed it.
Этот скриншот показывает распространённость конкретной ошибки (выделена жёлтым) в Lucy до (слева) и после (справа) того, как мы её устранили.
Level 2: Human & Model Eval
Уровень 2: Оценка человеком и моделью
After you have built a solid foundation of Level 1 tests, you can move on to other forms of validation that cannot be tested by assertions alone. A prerequisite to performing human and model-based eval is to log your traces.
После того как вы заложили прочный фундамент из тестов Уровня 1, можно переходить к другим формам валидации, которые невозможно проверить только утверждениями. Предварительное условие для проведения оценки человеком и на основе модели — логирование ваших трейсов.
Logging Traces
Логирование трейсов
A trace is a concept that has been around for a while in software engineering and is a log of a sequence of events such as user sessions or a request flow through a distributed system. In other words, tracing is a logical grouping of logs. In the context of LLMs, traces often refer to conversations you have with a LLM. For example, a user message, followed by an AI response, followed by another user message, would be an example of a trace.
Трейс — это понятие, давно существующее в разработке ПО, представляющее собой лог последовательности событий, таких как пользовательские сессии или путь запроса через распределённую систему. Иными словами, трейсинг — это логическая группировка логов. В контексте LLM трейсы часто означают разговоры, которые вы ведёте с LLM. Например, сообщение пользователя, за которым следует ответ ИИ, за которым следует ещё одно сообщение пользователя, — это пример трейса.
There are a growing number of solutions for logging LLM traces.2 Rechat uses LangSmith, which logs traces and allows you to view them in a human-readable way with an interactive playground to iterate on prompts. Sometimes, logging your traces requires you to instrument your code. In this case, Rechat was using LangChain which automatically logs trace events to LangSmith for you. Here is a screenshot of what this looks like:
Существует растущее число решений для логирования трейсов LLM.2 Rechat использует LangSmith, который логирует трейсы и позволяет просматривать их в удобочитаемом виде с интерактивной площадкой (playground) для итераций над промптами. Иногда логирование трейсов требует инструментирования вашего кода. В данном случае Rechat использовал LangChain, который автоматически логирует события трейсов в LangSmith за вас. Вот скриншот того, как это выглядит:
I like LangSmith - it doesn’t require that you use LangChain and is intuitive and easy to use. Searching, filtering, and reading traces are essential features for whatever solution you pick. I’ve found that some tools do not implement these basic functions correctly!
Мне нравится LangSmith — он не требует использования LangChain, интуитивно понятен и прост в применении. Поиск, фильтрация и чтение трейсов — важнейшие функции для любого решения, которое вы выберете. Я обнаружил, что некоторые инструменты реализуют эти базовые функции неправильно!
Looking At Your Traces
Просмотр ваших трейсов
You must remove all friction from the process of looking at data. This means rendering your traces in domain-specific ways. I’ve often found that it’s better to build my own data viewing & labeling tool so I can gather all the information I need onto one screen. In Lucy’s case, we needed to look at many sources of information (trace log, the CRM, etc) to understand what the AI did. This is precisely the type of friction that needs to be eliminated. In Rechat’s case, this meant adding information like:
Вы должны устранить всё трение в процессе просмотра данных. Это означает отображение ваших трейсов предметно-ориентированными способами. Я часто обнаруживал, что лучше создать собственный инструмент для просмотра и разметки данных, чтобы собрать всю нужную информацию на одном экране. В случае Lucy нам нужно было смотреть на множество источников информации (лог трейсов, CRM и т. д.), чтобы понять, что сделал ИИ. Это именно тот тип трения, который нужно устранить. В случае Rechat это означало добавление такой информации, как:
Какой инструмент (функция) и сценарий оценивались. Был ли трейс результатом синтетического ввода или реального пользовательского ввода. Фильтры для навигации между разными комбинациями инструментов и сценариев. Ссылки на CRM и систему логирования трейсов для текущей записи.
I’ve built different variations of this tool for each problem I’ve worked on. Sometimes, I even need to embed another application to see what the user interaction looks like. Below is a screenshot of the tool we built to evaluate Rechat’s traces:
Я создавал разные варианты этого инструмента для каждой задачи, над которой работал. Иногда мне даже приходится встраивать другое приложение, чтобы увидеть, как выглядит пользовательское взаимодействие. Ниже — скриншот инструмента, который мы построили для оценки трейсов Rechat:
Another design choice specific to Lucy is that we noticed that many failures involved small mistakes in the final output of the LLM (format, content, etc). We decided to make the final output editable by a human so that we could curate & fix data for fine-tuning.
Ещё одно проектное решение, специфичное для Lucy: мы заметили, что многие отказы связаны с мелкими ошибками в финальном выводе LLM (формат, содержание и т. д.). Мы решили сделать финальный вывод редактируемым человеком, чтобы можно было курировать и исправлять данные для fine-tuning.
These tools can be built with lightweight front-end frameworks like Gradio, Streamlit, Panel, or Shiny in less than a day. The tool shown above was built with Shiny for Python. Furthermore, there are tools like Lilac which uses AI to search and filter data semantically, which is incredibly handy for finding a set of similar data points while debugging an issue.
Эти инструменты можно создать с помощью лёгких фронтенд-фреймворков, таких как Gradio, Streamlit, Panel или Shiny, менее чем за день. Показанный выше инструмент был построен на Shiny for Python. Кроме того, есть инструменты вроде Lilac, который использует ИИ для семантического поиска и фильтрации данных, что невероятно удобно для нахождения набора похожих точек данных при отладке проблемы.
I often start by labeling examples as good or bad. I’ve found that assigning scores or more granular ratings is more onerous to manage than binary ratings. There are advanced techniques you can use to make human evaluation more efficient or accurate (e.g., active learning, consensus voting, etc.), but I recommend starting with something simple. Finally, like unit tests, you should organize and analyze your human-eval results to assess if you are progressing over time.
Я часто начинаю с разметки примеров как хороших или плохих. Я обнаружил, что присвоение баллов или более детальных рейтингов сложнее в управлении, чем бинарные оценки. Существуют продвинутые техники, которые можно использовать, чтобы сделать оценку человеком более эффективной или точной (напр., активное обучение, консенсусное голосование и т. д.), но я рекомендую начинать с чего-то простого. Наконец, как и в случае с юнит-тестами, вам следует организовывать и анализировать результаты оценки человеком, чтобы оценить, прогрессируете ли вы со временем.
As discussed later, these labeled examples measure the quality of your system, validate automated evaluation, and curate high-quality synthetic data for fine-tuning.
Как будет обсуждаться далее, эти размеченные примеры измеряют качество вашей системы, валидируют автоматизированную оценку и курируют высококачественные синтетические данные для fine-tuning.
How much data should you look at?
Сколько данных нужно просматривать?
I often get asked how much data to examine. When starting, you should examine as much data as possible. I usually read traces generated from ALL test cases and user-generated traces at a minimum. You can never stop looking at data—no free lunch exists. However, you can sample your data more over time, lessening the burden. 3
Меня часто спрашивают, сколько данных изучать. На старте стоит изучать как можно больше данных. Обычно я как минимум читаю трейсы, сгенерированные из ВСЕХ тестовых случаев, и трейсы, порождённые пользователями. Вы никогда не сможете перестать смотреть на данные — бесплатного сыра не бывает. Однако со временем вы можете больше прибегать к выборке из данных, снижая нагрузку.3
Automated Evaluation w/ LLMs
Автоматизированная оценка с помощью LLM
Many vendors want to sell you tools that claim to eliminate the need for a human to look at the data. Having humans periodically evaluate at least a sample of traces is a good idea. I often find that “correctness” is somewhat subjective, and you must align the model with a human.
Многие вендоры хотят продать вам инструменты, которые якобы устраняют необходимость в том, чтобы человек смотрел на данные. Хорошая идея — чтобы люди периодически оценивали хотя бы выборку трейсов. Я часто обнаруживаю, что «корректность» довольно субъективна, и вам нужно согласовать модель с человеком.
You should track the correlation between model-based and human evaluation to decide how much you can rely on automatic evaluation. Furthermore, by collecting critiques from labelers explaining why they are making a decision, you can iterate on the evaluator model to align it with humans through prompt engineering or fine-tuning. However, I tend to favor prompt engineering for evaluator model alignment.
Вам следует отслеживать корреляцию между оценкой на основе модели и оценкой человеком, чтобы решить, насколько вы можете полагаться на автоматическую оценку. Кроме того, собирая от разметчиков критические замечания с объяснением, почему они принимают то или иное решение, вы можете итерировать над моделью-оценщиком, чтобы согласовать её с людьми через промпт-инжиниринг или fine-tuning. Тем не менее для согласования модели-оценщика я склонен отдавать предпочтение промпт-инжинирингу.
I love using low-tech solutions like Excel to iterate on aligning model-based eval with humans. For example, I sent my colleague Phillip the following spreadsheet every few days to grade for a different use-case involving a natural language query generator. This spreadsheet would contain the following information:
Я обожаю использовать низкотехнологичные решения вроде Excel для итераций по согласованию оценки на основе модели с людьми. Например, я каждые несколько дней отправлял своему коллеге Филлипу следующую таблицу для оценки в другом сценарии использования, связанном с генератором запросов на естественном языке. Эта таблица содержала следующую информацию:
model response as being “good” or “bad.”ответ модели: это предсказание, сделанное LLM. критика модели: это критика, написанная (обычно более мощной) LLM о предсказании вашей исходной LLM. исход по модели: это бинарная метка, которую модель-критик присваивает ответу модели как «хорошему» или «плохому».
Phillip then fills out his version of the same information - meaning his critique, outcome, and desired response for 25-50 examples at a time (these are the columns prefixed with “phillip_” below):
Затем Филлип заполняет свою версию той же информации — то есть свою критику, исход и желаемый ответ — для 25–50 примеров за раз (это столбцы с префиксом «phillip_» ниже):
This information allowed me to iterate on the prompt of the critique model to make it sufficiently aligned with Phillip over time. This is also easy to track in a low-tech way in a spreadsheet:
Эта информация позволяла мне итерировать над промптом модели-критика, чтобы со временем достаточно хорошо согласовать её с Филлипом. Это тоже легко отслеживать низкотехнологичным способом в таблице:
This is a screenshot of a spreadsheet where we recorded our attempts to align model-based eval with a human evaluator.
Это скриншот таблицы, где мы фиксировали наши попытки согласовать оценку на основе модели с человеком-оценщиком.
General tips on model-based eval:
Общие советы по оценке на основе модели:
Используйте самую мощную модель, какую можете себе позволить. Чтобы хорошо что-то критиковать, часто требуются продвинутые способности к рассуждению. Для критики выводов нередко можно обойтись более медленной, но более мощной моделью, чем та, что используется в продакшене. Оценка на основе модели — это мета-проблема внутри вашей более крупной проблемы. Вам придётся поддерживать мини-систему оценки, чтобы отслеживать её качество. Иногда я делал fine-tuning модели на этом этапе (но стараюсь этого не делать). После того как вы привели модель-оценщик в соответствие с человеком, нужно продолжать периодически выполнять упражнения для мониторинга согласия модели и человека.
In this example, we used agreement between the model and human evaluator because our dataset was roughly balanced (about 50% of instances were failures). However, using raw agreement is generally not recommended and can be misleading when classes are imbalanced. Instead, you should typically measure precision and recall separately to get a more accurate picture of your judge’s alignment.
В этом примере мы использовали согласие между моделью и человеком-оценщиком, потому что наш набор данных был примерно сбалансирован (около 50% случаев были отказами). Однако использование сырого согласия в целом не рекомендуется и может вводить в заблуждение при несбалансированных классах. Вместо этого вам обычно следует измерять precision и recall по отдельности, чтобы получить более точную картину согласованности вашего судьи.
My favorite aspect about creating a good evaluator model is that its critiques can be used to curate high-quality synthetic data, which I will touch upon later.
Больше всего в создании хорошей модели-оценщика мне нравится то, что её критику можно использовать для курирования высококачественных синтетических данных, о чём я расскажу позже.
Level 3: A/B Testing
Уровень 3: A/B-тестирование
Finally, it is always good to perform A/B tests to ensure your AI product is driving user behaviors or outcomes you desire. A/B testing for LLMs compared to other types of products isn’t too different. If you want to learn more about A/B testing, I recommend reading the Eppo blog (which was created by colleagues I used to work with who are rock stars in A/B testing).
Наконец, всегда полезно проводить A/B-тесты, чтобы убедиться, что ваш ИИ-продукт стимулирует желаемое поведение или результаты пользователей. A/B-тестирование для LLM не слишком отличается от такового для других типов продуктов. Если вы хотите узнать больше об A/B-тестировании, я рекомендую почитать блог Eppo (созданный коллегами, с которыми я раньше работал и которые являются звёздами A/B-тестирования).
It’s okay to put this stage off until you are sufficiently ready and convinced that your AI product is suitable for showing to real users. This level of evaluation is usually only appropriate for more mature products.
Этот этап можно отложить, пока вы не будете достаточно готовы и убеждены, что ваш ИИ-продукт пригоден для показа реальным пользователям. Этот уровень оценки обычно уместен только для более зрелых продуктов.
Evaluating RAG
Оценка RAG
Aside from evaluating your system as a whole, you can evaluate sub-components of your AI, like RAG. Evaluating RAG is beyond the scope of this post, but you can learn more about this subject in a post by Jason Liu.
Помимо оценки вашей системы в целом, вы можете оценивать подкомпоненты вашего ИИ, такие как RAG. Оценка RAG выходит за рамки этого поста, но вы можете узнать больше об этой теме в посте Джейсона Лю.
Eval Systems Unlock Superpowers For Free
Системы оценки бесплатно открывают суперспособности
In addition to iterating fast, eval systems unlock the ability to fine-tune and debug, which can take your AI product to the next level.
Помимо быстрых итераций, системы оценки открывают возможность делать fine-tuning и отладку, что может вывести ваш ИИ-продукт на новый уровень.
Fine-Tuning
Fine-tuning
Rechat resolved many failure modes through fine-tuning that were not possible with prompt engineering alone. Fine-tuning is best for learning syntax, style, and rules, whereas techniques like RAG supply the model with context or up-to-date facts.
Rechat устранил множество режимов отказа через fine-tuning, которые были невозможны при одном лишь промпт-инжиниринге. Fine-tuning лучше всего подходит для изучения синтаксиса, стиля и правил, тогда как такие техники, как RAG, снабжают модель контекстом или актуальными фактами.
99% of the labor involved with fine-tuning is assembling high-quality data that covers your AI product’s surface area. However, if you have a solid evaluation system like Rechat’s, you already have a robust data generation and curation engine! I will expand more on the process of fine-tuning in a future post.4
99% труда, связанного с fine-tuning, — это сборка высококачественных данных, покрывающих весь охват вашего ИИ-продукта. Однако если у вас есть надёжная система оценки, как у Rechat, у вас уже есть мощный движок генерации и курирования данных! Подробнее о процессе fine-tuning я расскажу в будущем посте.4
Data Synthesis & Curation
Синтез и курирование данных
To illustrate why data curation and synthesis come nearly for free once you have an evaluation system, consider the case where you want to create additional fine-tuning data for the listing finder mentioned earlier. First, you can use LLMs to generate synthetic data with a prompt like this:
Чтобы проиллюстрировать, почему курирование и синтез данных достаются почти бесплатно, как только у вас есть система оценки, рассмотрим случай, когда вы хотите создать дополнительные данные для fine-tuning для упомянутого ранее поиска объявлений. Сначала вы можете использовать LLM для генерации синтетических данных с помощью такого промпта:
Imagine if Zillow was able to parse natural language. Come up with 50 different ways users would be able to search listings there. Use real names for cities and neighborhoods.
You can use the following parameters:
<omitted for confidentiality>
Output should be a JSON code block array. Example:
[
"Homes under $500k in New York"
]
Imagine if Zillow was able to parse natural language. Come up with 50 different ways users would be able to search listings there. Use real names for cities and neighborhoods. You can use the following parameters:
This is almost identical to the exercise for producing test cases! You can then use your Level 1 & Level 2 tests to filter out undesirable data that fails assertions or that the critique model thinks are wrong. You can also use your existing human evaluation tools to look at traces to curate traces for a fine-tuning dataset.
Это почти идентично упражнению по созданию тестовых случаев! Затем вы можете использовать свои тесты Уровня 1 и Уровня 2, чтобы отфильтровать нежелательные данные, которые не проходят утверждения или которые модель-критик считает ошибочными. Вы также можете использовать существующие инструменты оценки человеком для просмотра трейсов, чтобы курировать трейсы для набора данных fine-tuning.
Debugging
Отладка
When you get a complaint or see an error related to your AI product, you should be able to debug this quickly. If you have a robust evaluation system, you already have:
Когда вы получаете жалобу или видите ошибку, связанную с вашим ИИ-продуктом, вы должны уметь быстро её отладить. Если у вас есть надёжная система оценки, у вас уже есть:
База данных трейсов, которую можно искать и фильтровать. Набор механизмов (утверждения, тесты и т. д.), которые помогают помечать ошибки и плохое поведение. Инструменты поиска и навигации по логам, помогающие найти первопричину ошибки. Например, ошибкой может быть RAG, баг в коде или плохо работающая модель. Возможность вносить изменения в ответ на ошибку и быстро проверять их эффективность.
In short, there is an incredibly large overlap between the infrastructure needed for evaluation and that for debugging.
Короче говоря, существует невероятно большое пересечение между инфраструктурой, необходимой для оценки, и той, что нужна для отладки.
Conclusion
Заключение
Evaluation systems create a flywheel that allows you to iterate very quickly. It’s almost always where people get stuck when building AI products. I hope this post gives you an intuition on how to go about building your evaluation systems. Some key takeaways to keep in mind:
Системы оценки создают маховик, позволяющий вам очень быстро итерировать. Почти всегда именно здесь люди застревают при создании ИИ-продуктов. Надеюсь, этот пост даст вам интуицию о том, как подходить к построению ваших систем оценки. Несколько ключевых выводов, которые стоит держать в голове:
- Generate test cases and write assertions
- Generate synthetic data
- Critique and label data etc.
Устраните ВСЁ трение в просмотре данных. Держите всё простым. Не покупайте навороченные LLM-инструменты. Сначала используйте то, что у вас есть. Вы делаете что-то не так, если не смотрите на большое количество данных. Не полагайтесь на универсальные фреймворки оценки для измерения качества вашего ИИ. Вместо этого создайте систему оценки, специфичную для вашей задачи. Пишите много тестов и часто их обновляйте. LLM можно использовать, чтобы разблокировать создание системы оценки. Примеры включают использование LLM для: генерации тестовых случаев и написания утверждений, генерации синтетических данных, критики и разметки данных и т. д. Переиспользуйте свою инфраструктуру оценки для отладки и fine-tuning.
I’d love to hear from you if you found this post helpful or have any questions. My email is hamel@parlance-labs.com.
Буду рад услышать от вас, если этот пост оказался полезным или если у вас есть вопросы. Моя почта: hamel@parlance-labs.com.
This article is an adaptation of this conversation I had with Emil Sedgh and Hugo Browne-Anderson on the Vanishing Gradients podcast. Thanks to Jeremy Howard, Eugene Yan, Shreya Shankar, Jeremy Lewi, and Joseph Gleasure for reviewing this article.
Эта статья — адаптация этого разговора, который у меня состоялся с Emil Sedgh и Hugo Browne-Anderson в подкасте Vanishing Gradients. Спасибо Jeremy Howard, Eugene Yan, Shreya Shankar, Jeremy Lewi и Joseph Gleasure за рецензирование этой статьи.
Footnotes
Сноски
This is not to suggest that people are lazy. Many don’t know how to set up eval systems and skip these steps.↩︎
Some examples include arize, human loop, openllmetry and honeyhive.↩︎
A reasonable heuristic is to keep reading logs until you feel like you aren’t learning anything new.↩︎
If you cannot wait, I’ll be teaching this course on fine-tuning soon.↩︎
Это не значит, что люди ленивы. Многие просто не знают, как настроить системы оценки, и пропускают эти шаги.↩︎ Среди примеров — arize, human loop, openllmetry и honeyhive.↩︎ Разумная эвристика — продолжать читать логи, пока не почувствуете, что больше не узнаёте ничего нового.↩︎ Если ждать невмоготу, я скоро буду вести этот курс по fine-tuning.↩︎