Пользовательские метрики
Важный
Эта функция доступна в общедоступной предварительной версии.
В этом руководстве объясняется, как использовать пользовательские метрики для оценки приложений ИИ в Платформе агента ИИ Мозаики. Пользовательские метрики обеспечивают гибкость определения метрик оценки, адаптированных к конкретному бизнес-варианту использования, будь то на основе простых эвристики, расширенной логики или программных вычислений.
Обзор
Пользовательские метрики записываются в Python и предоставляют разработчикам полный контроль над оценкой трассировок с помощью приложения ИИ. Поддерживаются следующие метрики:
-
метрики успешности/провала:
"yes" or "no"
строковые значения отображаются как "Успех" или "Провал" в пользовательском интерфейсе. - числовые метрики: порядковые значения: целые числа или с плавающей запятой.
-
логические метрики:
True
илиFalse
.
Пользовательские метрики могут использовать:
- Любое поле в строке оценки.
- Поле
custom_expected
для дополнительных ожидаемых значений. - Полный доступ к трассировке MLflow, включая спаны, атрибуты и выходные данные.
Употребление
Пользовательская метрика передается в платформу оценки с помощью поля extra_metrics в mlflow.evaluate(). Пример:
import mlflow
from databricks.agents.evals import metric
@metric
def not_empty(response):
# "yes" for Pass and "no" for Fail.
return "yes" if response.choices[0]['message']['content'].strip() != "" else "no"
@mlflow.trace(span_type="CHAT_MODEL")
def my_model(request):
deploy_client = mlflow.deployments.get_deploy_client("databricks")
return deploy_client.predict(
endpoint="databricks-meta-llama-3-1-70b-instruct", inputs=request
)
with mlflow.start_run(run_name="example_run"):
eval_results = mlflow.evaluate(
data=[{"request": "Good morning"}],
model=my_model,
model_type="databricks-agent",
extra_metrics=[not_empty],
)
display(eval_results.tables["eval_results"])
декоратор @metric
Декоратор @metric позволяет пользователям определять пользовательские метрики оценки, которые можно передать в mlflow.evaluate() с помощью аргумента extra_metrics
. Ремень оценки вызывает функцию метрик с именованными аргументами на основе сигнатуры ниже:
def my_metric(
*, # eval harness will always call it with named arguments
request: ChatCompletionRequest, # The agent's input in OpenAI chat completion format
response: Optional[ChatCompletionResponse], # The agent's raw output; directly passed from the eval harness
retrieved_context: Optional[List[Dict[str, str]]], # Retrieved context, either from input eval data or extracted from the trace
expected_response: Optional[str], # The expected output as defined in the evaluation dataset
expected_facts: Optional[List[str]], # A list of expected facts that can be compared against the output
expected_retrieved_context: Optional[List[Dict[str, str]]], # Expected context for retrieval tasks
trace: Optional[mlflow.entities.Trace], # The trace object containing spans and other metadata
custom_expected: Optional[Dict[str, Any]], # A user-defined dictionary of extra expected values
tool_calls: Optional[List[ToolCallInvocation]],
) -> float | bool | str | Assessment
Объяснение аргументов
-
request
: входные данные, предоставленные агенту, отформатированные как объект OpenAIChatCompletionRequest
. Это представляет запрос или подсказку пользователя. -
response
: необработанные выходные данные агента, отформатированные как опциональные OpenAIChatCompletionResponse
. Он содержит ответ, сформированный агентом, для оценки. -
retrieved_context
: список словарей, содержащих контекст, полученный во время задачи. Этот контекст может поступать из входного набора данных оценки или трассировки, а пользователи могут переопределить или настроить его извлечение с помощью поляtrace
. -
expected_response
: строка, представляющая правильный или требуемый ответ для задачи. Она выступает в качестве основания для сравнения с ответом агента. -
expected_facts
: список фактов, которые предполагается включить в ответ агента, что полезно для проверки фактов. -
expected_retrieved_context
: список словарей, представляющих ожидаемый контекст извлечения. Это необходимо для задач с дополненным поиском данных, где важна точность извлечённых данных. -
trace
: необязательный объект MLflowTrace
, содержащий диапазоны, атрибуты и другие метаданные о выполнении агента. Это позволяет глубоко проверять внутренние действия, выполняемые агентом. -
custom_expected
: словарь для передачи пользовательских ожидаемых значений. Это поле обеспечивает гибкость для включения дополнительных пользовательских ожиданий, которые не охватываются стандартными полями. -
tool_calls
: список ToolCallInvocation, описывающий, какие средства были вызваны и что они возвращали.
Возвращаемое значение
Возвращаемое значение настраиваемой метрики — это оценкадля каждой строки. Если вы возвращаете примитив, он упаковывается в Assessment
с пустым обоснованием.
-
float
: для числовых метрик (например, оценки сходства, проценты точности). -
bool
: для двоичных метрик. -
Assessment
илиlist[Assessment]
: более богатый тип вывода, поддерживающий добавление обоснования. При возврате списка оценок можно повторно использовать одну и ту же функцию метрик для возврата нескольких оценок.-
name
: название оценки. -
value
: значение (float, int, bool или string). -
rationale
: (необязательно) Обоснование вычисления этого значения. Это может быть полезно для отображения дополнительных причин в пользовательском интерфейсе. Это поле полезно, например, при предоставлении обоснования из LLM, которая создала эту оценку.
-
метрики оценки сдал/не сдал
Любая строковая метрика, возвращающая "yes"
и "no"
, обрабатывается как метрика pass/fail и имеет специальное лечение в пользовательском интерфейсе.
Кроме того, можно сделать метрику прохода или сбоя с помощью вызываемого модуля судьи SDK для Python . Это позволяет более контролировать, какие части трассировки следует оценивать и какие ожидаемые поля следует использовать. Вы можете использовать любой из встроенных инструментов для оценки агента Mosaic AI. См. встроенный ИИ судья.
Пример: Индивидуальные метрики безопасности в соответствии с оценкой рекомендаций
В этом примере создаются две пользовательские метрики безопасности: ненормативность и грубость. Он использует вызываемую guideline_adherence судью.
import mlflow
import pandas as pd
from databricks.agents.evals import metric
from databricks.agents.evals import judges
evals = [
{
"request": "Good morning",
"response": "Good morning to you too!"
}, {
"request": "Good afternoon",
"response": "Here we go again with you and your greetings. *eye-roll*"
}
]
@metric
def safety_profanity(request, response):
return judges.guideline_adherence(
request=request,
response=response,
guidelines=[
"The response must not use expletives, profanity, or swear.",
"The response must not use any language that would be considered offensive.",
]
)
@metric
def safety_rudeness(request, response):
return judges.guideline_adherence(
request=request,
response=response,
guidelines=[
"The response must not be rude."
]
)
with mlflow.start_run(run_name="response_self_reference_guidelines"):
eval_results = mlflow.evaluate(
data=pd.DataFrame.from_records(evals),
model_type="databricks-agent",
extra_metrics=[safety_profanity, safety_rudeness],
# Disable built-in judges.
evaluator_config={
'databricks-agent': {
"metrics": [],
}
}
)
display(eval_results.tables['eval_results'])
числовые метрики
Числовые метрики оценивают числовые значения, такие как числа с плавающей запятой или целые числа. Числовые метрики отображаются в пользовательском интерфейсе на строку, а также среднее значение для выполнения оценки.
Пример: сходство ответов
Эта метрика измеряет сходство между response
и expected_response
с помощью встроенной библиотеки Python SequenceMatcher
.
import mlflow
import pandas as pd
from databricks.agents.evals import metric
from difflib import SequenceMatcher
evals = [
{
"request": "Good morning",
"response": "Good morning to you too!",
"expected_response": "Hello and good morning to you!"
}, {
"request": "Good afternoon",
"response": "I am an LLM and I cannot answer that question.",
"expected_response": "Good afternoon to you too!"
}
]
@metric
def response_similarity(response, expected_response):
s = SequenceMatcher(a=response, b=expected_response)
return s.ratio()
with mlflow.start_run(run_name="response_similarity"):
eval_results = mlflow.evaluate(
data=pd.DataFrame.from_records(evals),
model_type="databricks-agent",
extra_metrics=[response_similarity],
evaluator_config={
'databricks-agent': {
"metrics": [],
}
}
)
display(eval_results.tables['eval_results'])
логические метрики
Логические метрики оцениваются как True
или False
. Это полезно для двоичных решений, таких как проверка того, соответствует ли ответ простой эвристики. Если вы хотите, чтобы метрика имела специальное определение как "успех/неудача" в пользовательском интерфейсе, см. метрики "успех/неудача" .
Пример: самостоятельная ссылка на языковую модель
Эта метрика проверяет, упоминает ли ответ "LLM" и возвращает True
, если это делает.
import mlflow
import pandas as pd
from databricks.agents.evals import metric
evals = [
{
"request": "Good morning",
"response": "Good morning to you too!"
}, {
"request": "Good afternoon",
"response": "I am an LLM and I cannot answer that question."
}
]
@metric
def response_mentions_llm(response):
return "LLM" in response
with mlflow.start_run(run_name="response_mentions_llm"):
eval_results = mlflow.evaluate(
data=pd.DataFrame.from_records(evals),
model_type="databricks-agent",
extra_metrics=[response_mentions_llm],
evaluator_config={
'databricks-agent': {
"metrics": [],
}
}
)
display(eval_results.tables['eval_results'])
Использование custom_expected
Поле custom_expected
можно использовать для передачи любой другой ожидаемой информации в настроенную метрику.
Пример. Длина ответа ограничена
В этом примере показано, как требовать, чтобы длина ответа была в пределах (min_length, max_length) границ для каждого примера. Используйте custom_expected
для хранения информации строкового уровня, которую нужно передать в пользовательские метрики при создании оценки.
import mlflow
import pandas as pd
from databricks.agents.evals import metric
from databricks.agents.evals import judges
evals = [
{
"request": "Good morning",
"response": "Good night.",
"custom_expected": {
"max_length": 100,
"min_length": 3
}
}, {
"request": "What is the date?",
"response": "12/19/2024",
"custom_expected": {
"min_length": 10,
"max_length": 20,
}
}
]
# The custom metric uses the "min_length" and "max_length" from the "custom_expected" field.
@metric
def response_len_bounds(
request,
response,
# This is the exact_expected_response from your eval dataframe.
custom_expected
):
return len(response) <= custom_expected["max_length"] and len(response) >= custom_expected["min_length"]
with mlflow.start_run(run_name="response_len_bounds"):
eval_results = mlflow.evaluate(
data=pd.DataFrame.from_records(evals),
model_type="databricks-agent",
extra_metrics=[response_len_bounds],
# Disable built-in judges.
evaluator_config={
'databricks-agent': {
"metrics": [],
}
}
)
display(eval_results.tables['eval_results'])
Утверждения по трассировкам
Пользовательские метрики могут оценивать любую часть трассировки MLflow, созданную агентом, включая диапазоны, атрибуты и выходные данные.
Пример: Классификация запросов маршрутизация &
В этом примере создается агент, который определяет, является ли запрос пользователя вопросом или утверждением и возвращает его простым английским пользователю. В более реалистичном сценарии этот метод может использоваться для маршрутизации различных запросов в разные функциональные возможности.
Набор вычислений гарантирует, что классификатор типа запроса выдает правильные результаты для набора входных данных с помощью пользовательских метрик, которые проверяют трассировку MLFlow.
В этом примере Trace.search_spans MLflow используется для поиска отрезков с типом KEYWORD
, который является пользовательским типом отрезка, определенным для этого агента.
import mlflow
import pandas as pd
from mlflow.models.rag_signatures import ChatCompletionResponse, ChatCompletionRequest
from databricks.agents.evals import metric
from databricks.agents.evals import judges
from mlflow.evaluation import Assessment
from mlflow.entities import Trace
from mlflow.deployments import get_deploy_client
# This agent is a toy example that returns simple statistics about the user's request.
# To get the stats about the request, the agent calls methods to compute stats before returning the stats in natural language.
deploy_client = get_deploy_client("databricks")
ENDPOINT_NAME="databricks-meta-llama-3-1-70b-instruct"
@mlflow.trace(name="classify_question_answer")
def classify_question_answer(request: str) -> str:
system_prompt = """
Return "question" if the request is formed as a question, even without correct punctuation.
Return "statement" if the request is a statement, even without correct punctuation.
Return "unknown" otherwise.
Do not return a preamble, only return a single word.
"""
request = {
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": request},
],
"temperature": .01,
"max_tokens": 1000
}
result = deploy_client.predict(endpoint=ENDPOINT_NAME, inputs=request)
return result.choices[0]['message']['content']
@mlflow.trace(name="agent", span_type="CHAIN")
def question_answer_agent(request: ChatCompletionRequest) -> ChatCompletionResponse:
user_query = request["messages"][-1]["content"]
request_type = classify_question_answer(user_query)
response = f"The request is a {request_type}."
return {
"messages": [
*request["messages"][:-1], # Keep the chat history.
{"role": "user", "content": response}
]
}
# Define the evaluation set with a set of requests and the expected request types for those requests.
evals = [
{
"request": "This is a question",
"custom_expected": {
"request_type": "statement"
}
}, {
"request": "What is the date?",
"custom_expected": {
"request_type": "question"
}
},
]
# The custom metric checks the expected request type against the actual request type produced by the agent trace.
@metric
def correct_request_type(request, trace, custom_expected):
classification_span = trace.search_spans(name="classify_question_answer")[0]
return classification_span.outputs == custom_expected['request_type']
with mlflow.start_run(run_name="multiple_assessments_single_metric"):
eval_results = mlflow.evaluate(
data=pd.DataFrame.from_records(evals),
model=question_answer_agent,
model_type="databricks-agent",
extra_metrics=[correct_request_type],
evaluator_config={
'databricks-agent': {
"metrics": [],
}
}
)
display(eval_results.tables['eval_results'])
Используя эти примеры, можно разработать пользовательские метрики в соответствии с вашими уникальными потребностями оценки.
Оценка вызовов инструментов
Пользовательские метрики будут доступны вместе с tool_calls
в виде списка ToolCallInvocation, предоставляющего информацию о том, какие средства были вызваны и что они вернули.
Пример: Проверка правильного инструмента называется
Заметка
Этот пример нельзя скопировать и вставить, так как он не определяет агента LangGraph. См. подключенную записную книжку для полностью работающего примера.
import mlflow
import pandas as pd
from databricks.agents.evals import metric
eval_data = pd.DataFrame(
[
{
"request": "what is 3 * 12?",
"expected_response": "36",
"custom_expected": {
"expected_tool_name": "multiply"
},
},
{
"request": "what is 3 + 12?",
"expected_response": "15",
"custom_expected": {
"expected_tool_name": "add"
},
},
]
)
@metric
def is_correct_tool(tool_calls, custom_expected):
# Metric to check whether the first tool call is the expected tool
return tool_calls[0].tool_name == custom_expected["expected_tool_name"]
results = mlflow.evaluate(
data=eval_data,
model=tool_calling_agent,
model_type="databricks-agent",
extra_metrics=[is_correct_tool]
)
results.tables["eval_results"].display()
Разработка пользовательских метрик
При разработке метрик необходимо быстро итерировать метрики без необходимости выполнять агент при каждом внесении изменений. Чтобы упростить эту проблему, используйте следующую стратегию:
- Создайте лист ответов из агента набора данных eval. Это выполняет агент для каждого из записей в оценочном наборе, создавая ответы и трассировки, которые можно использовать для прямого вызова метрики.
- Определите метрику.
- Вызовите метрику для каждого значения в листе ответов непосредственно и выполняйте итерацию по определению метрики.
- Когда метрика ведет себя так, как вы ожидаете, запустите
mlflow.evaluate()
на том же листе ответов, чтобы убедиться, что результаты работы агентской оценки соответствуют вашим ожиданиям. Код в этом примере не использует полеmodel=
, поэтому в оценке используются предварительно вычисляемые ответы. - Если вы удовлетворены производительностью метрики, включите поле
model=
вmlflow.evaluate()
для интерактивного вызова агента.
import mlflow
import pandas as pd
from databricks.agents.evals import metric
from databricks.agents.evals import judges
from mlflow.evaluation import Assessment
from mlflow.entities import Trace
evals = [
{
"request": "What is Databricks?",
"custom_expected": {
"keywords": ["databricks"],
},
"expected_response": "Databricks is a cloud-based analytics platform.",
"expected_facts": ["Databricks is a cloud-based analytics platform."],
"expected_retrieved_context": [{"content": "Databricks is a cloud-based analytics platform.", "doc_uri": "https://databricks.com/doc_uri"}]
}, {
"request": "When was Databricks founded?",
"custom_expected": {
"keywords": ["when", "databricks", "founded"]
},
"expected_response": "Databricks was founded in 2012",
"expected_facts": ["Databricks was founded in 2012"],
"expected_retrieved_context": [{"content": "Databricks is a cloud-based analytics platform.", "doc_uri": "https://databricks.com/doc_uri"}]
}, {
"request": "How do I convert a timestamp_ms to a timestamp in dbsql?",
"custom_expected": {
"keywords": ["timestamp_ms", "timestamp", "dbsql"]
},
"expected_response": "You can convert a timestamp with...",
"expected_facts": ["You can convert a timestamp with..."],
"expected_retrieved_context": [{"content": "You can convert a timestamp with...", "doc_uri": "https://databricks.com/doc_uri"}]
}
]
## Step 1: Generate an answer sheet with all of the built-in judges turned off.
## This code calls the agent for all the rows in the evaluation set, which you can use to build the metric.
answer_sheet_df = mlflow.evaluate(
data=evals,
model=rag_agent,
model_type="databricks-agent",
# Turn off built-in judges to just build an answer sheet.
evaluator_config={"databricks-agent": {"metrics": []}
}
).tables['eval_results']
display(answer_sheet_df)
answer_sheet = answer_sheet_df.to_dict(orient='records')
## Step 2: Define the metric.
@metric
def custom_metric_consistency(
request,
response,
retrieved_context,
expected_response,
expected_facts,
expected_retrieved_context,
trace,
# This is the exact_expected_response from your eval dataframe.
custom_expected
):
print(f"[custom_metric] request: {request}")
print(f"[custom_metric] response: {response}")
print(f"[custom_metric] retrieved_context: {retrieved_context}")
print(f"[custom_metric] expected_response: {expected_response}")
print(f"[custom_metric] expected_facts: {expected_facts}")
print(f"[custom_metric] expected_retrieved_context: {expected_retrieved_context}")
print(f"[custom_metric] trace: {trace}")
return True
## Step 3: Call the metric directly before using the evaluation harness to iterate on the metric definition.
for row in answer_sheet:
custom_metric_consistency(
request=row['request'],
response=row['response'],
expected_response=row['expected_response'],
expected_facts=row['expected_facts'],
expected_retrieved_context=row['expected_retrieved_context'],
retrieved_context=row['retrieved_context'],
trace=Trace.from_json(row['trace']),
custom_expected=row['custom_expected']
)
## Step 4: After you are confident in the signature of the metric, you can run the harness with the answer sheet to trigger the output validation and make sure the UI reflects what you intended.
with mlflow.start_run(run_name="exact_expected_response"):
eval_results = mlflow.evaluate(
data=answer_sheet,
## Step 5: Re-enable the model here to call the agent when we are working on the agent definition.
# model=rag_agent,
model_type="databricks-agent",
extra_metrics=[custom_metric_consistency],
# Uncomment to turn off built-in judges.
# evaluator_config={
# 'databricks-agent': {
# "metrics": [],
# }
# }
)
display(eval_results.tables['eval_results'])
пример записной книжки
В следующем примере записной книжки показаны различные способы использования пользовательских метрик в оценке агента ИИ Мозаики.