Metryki niestandardowe
Ważny
Ta funkcja jest dostępna w publicznej wersji testowej.
W tym przewodniku wyjaśniono, jak używać niestandardowych metryk do oceny aplikacji sztucznej inteligencji w ramach Mosaic AI Agent Framework. Metryki niestandardowe zapewniają elastyczność definiowania metryk oceny dostosowanych do konkretnego przypadku użycia biznesowego, niezależnie od tego, czy są oparte na prostych heurystyce, zaawansowanej logice czy ocenach programowych.
Przegląd
Wskaźniki niestandardowe są zapisywane w języku Python i dają deweloperom pełną kontrolę do oceny śladów przy użyciu aplikacji AI. Obsługiwane są następujące metryki:
-
metryki zaliczone/niezaliczone:
"yes" or "no"
wartości tekstowe są wyświetlane jako "Zaliczone" lub "Niezaliczone" w interfejsie użytkownika. - metryki liczbowe: wartości porządkowe: liczby całkowite lub zmiennoprzecinkowe.
-
metryki logiczne:
True
lubFalse
.
Niestandardowych metryk można używać:
- Dowolne pole w wierszu oceny.
- Pole
custom_expected
dla dodatkowych oczekiwanych wartości. - Pełny dostęp do śledzenia MLflow, w tym zakresów, atrybutów i danych wyjściowych.
Użycie
Metryka niestandardowa jest przekazywana do struktury oceny przy użyciu pola extra_metrics w pliku mlflow.evaluate(). Przykład:
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"])
dekorator @metric
Dekorator @metric umożliwia użytkownikom definiowanie niestandardowych metryk oceny, które można przekazać do mlflow.evaluate() przy użyciu argumentu extra_metrics
. Narzędzie oceny wywołuje funkcję metryczną z nazwanymi argumentami na podstawie poniższej sygnatury.
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
Wyjaśnienie argumentów
-
request
: dane wejściowe dostarczone do agenta sformatowane jako obiektChatCompletionRequest
OpenAI. Reprezentuje to zapytanie użytkownika lub monit. -
response
: Surowe dane wyjściowe z agenta, sformatowane jako opcjonalny format OpenAIChatCompletionResponse
. Zawiera on wygenerowaną odpowiedź agenta na potrzeby oceny. -
retrieved_context
: lista słowników zawierających kontekst pobrany podczas zadania. Ten kontekst może pochodzić z wejściowego zestawu danych oceny lub śledzenia, a użytkownicy mogą przesłonić lub dostosować wyodrębnianie za pomocą polatrace
. -
expected_response
: ciąg reprezentujący poprawną lub żądaną odpowiedź dla zadania. Służy jako prawdziwa podstawa do porównania z odpowiedzią agenta. -
expected_facts
: lista faktów, które powinny pojawić się w odpowiedzi agenta, przydatne w przypadku zadań sprawdzania faktów. -
expected_retrieved_context
: lista słowników reprezentujących oczekiwany kontekst pobierania. Jest to niezbędne w przypadku zadań rozszerzonych pobierania, w których istotna jest poprawność pobranych danych. -
trace
: opcjonalny obiekt MLflowTrace
zawierający zakresy, atrybuty i inne metadane dotyczące wykonywania agenta. Pozwala to na głęboką inspekcję wewnętrznych kroków podjętych przez agenta. -
custom_expected
: słownik do przekazywania wartości oczekiwanych zdefiniowanych przez użytkownika. To pole zapewnia elastyczność dołączania dodatkowych oczekiwań niestandardowych, które nie są objęte polami standardowymi. -
tool_calls
: Lista ToolCallInvocation, która opisuje, które narzędzia zostały wywołane i co zwróciły.
Wartość zwracana
Wartość zwracana metryki niestandardowej jest przypadająca na wiersz w schemacie Assessment. Jeśli zwracasz element pierwotny, jest on owinięty w Assessment
z pustym uzasadnieniem.
-
float
: w przypadku metryk liczbowych (np. wyników podobieństwa, wartości procentowe dokładności). -
bool
: w przypadku metryk binarnych. -
Assessment
lublist[Assessment]
: bogatszy typ danych wyjściowych obsługujący dodawanie uzasadnienia. Jeśli zwrócisz listę ocen, ta sama funkcja metryki może zostać ponownie użyta do zwrócenia wielu ocen.-
name
: nazwa oceny. -
value
: wartość (liczba zmiennoprzecinkowa, liczba całkowita, boolean lub ciąg). -
rationale
: (Opcjonalnie) Uzasadnienie objaśniające sposób obliczania tej wartości. Może to być przydatne, aby pokazać dodatkowe rozumowanie w interfejsie użytkownika. To pole jest przydatne, na przykład podczas podawania rozumowania z modelu LLM, który wygenerował tę ocenę.
-
metryki zdane/oblane
Każda metryka ciągu zwracająca "yes"
i "no"
jest traktowana jako metryka pass/fail i ma specjalne traktowanie w interfejsie użytkownika.
Możesz również utworzyć metrykę zaliczenie/niezaliczenie za pomocą wywoływanego sędziego z zestawu SDK dla języka Python . To daje ci większą kontrolę nad tym, które części śladu oceniać i które oczekiwane pola stosować. Możesz użyć dowolnych wbudowanych sędziów oceny agentów AI Mozaiki. Zobacz wbudowaną AI oceniającą.
Przykład: niestandardowe metryki bezpieczeństwa zgodnie z wytycznymi
W tym przykładzie są tworzone dwa niestandardowe metryki bezpieczeństwa: wulgarność i niegrzeczność. Używa obiektu callable 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'])
metryki liczbowe
Metryki liczbowe oceniają wartości porządkowe, takie jak liczba zmiennoprzecinkowa lub liczba całkowita. Metryki liczbowe są wyświetlane w interfejsie użytkownika na wiersz wraz ze średnią wartością przebiegu oceny.
Przykład: podobieństwo odpowiedzi
Ta metryka mierzy podobieństwo między response
a expected_response
przy użyciu wbudowanej biblioteki języka 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'])
metryki boolowskie
Metryki logiczne przyjmują wartość True
lub False
. Są one przydatne w przypadku decyzji binarnych, takich jak sprawdzanie, czy odpowiedź spełnia prostą heurystyczną. Jeśli chcesz, aby metryka miała specjalne podejście "pass/fail" w interfejsie użytkownika, zobacz metryki "pass/fail".
Przykład: Odniesienie do samego siebie modelu językowego
Ta metryka sprawdza, czy odpowiedź wspomina "LLM" i zwraca True
, jeśli tak.
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'])
Korzystanie z custom_expected
Pole custom_expected
może być używane do przekazywania wszelkich innych oczekiwanych informacji do metryki niestandardowej.
Przykład: długość odpowiedzi ograniczona
W tym przykładzie pokazano, jak wymagać, aby długość odpowiedzi mieściła się w granicach (min_length, max_length) ustawionych dla każdego przykładu. Użyj custom_expected
do przechowywania dowolnych informacji na poziomie wiersza, które mają być przekazywane do metryk niestandardowych podczas tworzenia oceny.
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'])
Potwierdzenia dotyczące śladów
Metryki niestandardowe mogą oceniać dowolną część śladu MLflow generowanego przez agenta, w tym rozpiętości, atrybuty i dane wyjściowe.
Przykład: routing & klasyfikacji żądań
W tym przykładzie utworzono agenta, który określa, czy zapytanie użytkownika jest pytaniem, czy instrukcją i zwraca je w języku angielskim dla użytkownika. W bardziej realistycznym scenariuszu można użyć tej techniki do kierowania różnych zapytań do różnych funkcji.
Zestaw oceny zapewnia, że klasyfikator typu zapytania generuje odpowiednie wyniki dla zestawu danych wejściowych przy użyciu metryk niestandardowych, które sprawdzają ślad MLFlow.
W tym przykładzie użyto MLflow Trace.search_spans do znalezienia zakresów typu KEYWORD
, który jest niestandardowym typem zakresu zdefiniowanym dla tego agenta.
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'])
Korzystając z tych przykładów, można zaprojektować metryki niestandardowe w celu spełnienia unikatowych potrzeb oceny.
Ocenianie wywołań narzędzi
Metryki niestandardowe będą dostarczane z tool_calls
, które stanowią listę wywołań ToolCallInvocation, dającą informacje o tym, które narzędzia zostały wywołane i co zwróciły.
Przykład: potwierdzanie właściwego narzędzia
Notatka
Ten przykład nie jest możliwy do skopiowania, ponieważ nie definiuje agenta LangGraph. Zapoznaj się z dołączonym notesem , aby uzyskać w pełni uruchamialny przykład.
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()
Opracowywanie metryk niestandardowych
Podczas opracowywania metryk należy szybko iterować metrykę bez konieczności wykonywania agenta za każdym razem, gdy wprowadzisz zmianę. Aby to ułatwić, użyj następującej strategii:
- Wygeneruj arkusz odpowiedzi przy użyciu agenta zestawu danych ewaluacyjnych. Wykonuje agenta dla każdego wpisu w zestawie oceny, oraz generuje odpowiedzi i ślady, których można użyć do bezpośredniego wywołania metryki.
- Zdefiniuj metryki.
- Wywołaj metrykę dla każdej wartości w arkuszu odpowiedzi bezpośrednio i przejrzyj definicję metryki.
- Gdy metryka działa zgodnie z oczekiwaniami, uruchom
mlflow.evaluate()
w tym samym arkuszu odpowiedzi, aby sprawdzić, czy wyniki z uruchomienia Oceny Agenta są takie, jakich oczekujesz. Kod w tym przykładzie nie używa polamodel=
, więc ocena używa wstępnie obliczonych odpowiedzi. - Jeśli wydajność metryki jest satysfakcjonująca, włącz pole
model=
wmlflow.evaluate()
, aby wywołać agenta interaktywnie.
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'])
Przykładowy notatnik
Poniższy przykładowy notes ilustruje kilka różnych sposobów używania metryk niestandardowych w narzędziu Mosaic AI Agent Evaluation.