Anpassade mått
Viktig
Den här funktionen finns i offentlig förhandsversion.
Den här guiden beskriver hur du använder anpassade mått för att utvärdera AI-program i Mosaic AI Agent Framework. Anpassade mått ger flexibilitet att definiera utvärderingsmått som är skräddarsydda för ditt specifika affärsanvändningsfall, oavsett om de baseras på enkel heuristik, avancerad logik eller programmatiska utvärderingar.
Överblick
Anpassade mått skrivs i Python och ger utvecklare fullständig kontroll för att utvärdera spårningar via ett AI-program. Följande mått stöds:
-
mått för pass/fail:
"yes" or "no"
strängvärden återges som "Pass" eller "Fail" i användargränssnittet. - Numeriska mått: Ordinalvärden: heltal eller flyttal.
-
booleska mått:
True
ellerFalse
.
Anpassade mått kan använda sig av:
- Valfritt fält i utvärderingsraden.
- Fältet
custom_expected
för ytterligare förväntade värden. - Fullständig åtkomst till MLflow-spårningen, inklusive intervall, attribut och utdata.
Användning
Det anpassade måttet skickas till utvärderingsramverket med hjälp av fältet extra_metrics i mlflow.evaluate(). Exempel:
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
dekoratör
Med @metric dekoratör kan användarna definiera anpassade utvärderingsmått som kan skickas till mlflow.evaluate() med argumentet extra_metrics
. Utvärderingsramverket anropar måttfunktionen med namngivna argument baserat på signatur nedan:
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
Förklaring av argument
-
request
: Indata som tillhandahålls till agenten, formaterad som ett OpenAI-ChatCompletionRequest
-objekt. Detta representerar användarens fråga eller begäran. -
response
: Råutdata från agenten, formaterad som en valfri OpenAI-ChatCompletionResponse
. Den innehåller agentens genererade svar för utvärdering. -
retrieved_context
: En lista över ordlistor som innehåller kontext som hämtats under aktiviteten. Den här kontexten kan komma från datauppsättningen för utvärdering av indata eller spårningen, och användarna kan åsidosätta eller anpassa extraheringen via fältettrace
. -
expected_response
: Strängen som representerar rätt eller önskat svar för uppgiften. Den fungerar som grundsanning för jämförelse mot agentens svar. -
expected_facts
: En lista över fakta som förväntas visas i agentens svar, användbar för faktakontrolluppgifter. -
expected_retrieved_context
: En lista med ordlistor som representerar den förväntade hämtningskontexten. Detta är viktigt för återhämtningsförstärkta uppgifter där korrektheten i de hämtade uppgifterna spelar roll. -
trace
: Ett valfritt MLflow-Trace
objekt som innehåller intervall, attribut och andra metadata om agentens körning. Detta möjliggör djupgranskning av de interna åtgärder som agenten vidtar. -
custom_expected
: En ordlista för att skicka användardefinierade förväntade värden. Det här fältet ger flexibilitet att inkludera ytterligare anpassade förväntningar som inte omfattas av standardfälten. -
tool_calls
: En lista över ToolCallInvocation som beskriver vilka verktyg som anropades och vad de returnerade.
Returvärde
Returvärdet för det anpassade måttet är en bedömningper rad. Om du returnerar en primitiv, är den insvept i en Assessment
med en tom logik.
-
float
: För numeriska mått (t.ex. likhetspoäng, noggrannhetsprocent). -
bool
: För binära mått. -
Assessment
ellerlist[Assessment]
: En mer omfattande utdatatyp som har stöd för att lägga till en logik. Om du returnerar en lista över utvärderingar kan samma måttfunktion återanvändas för att returnera flera utvärderingar.-
name
: Namnet på utvärderingen. -
value
: Värdet (en flyttal, int, bool eller sträng). -
rationale
: (Valfritt) En motivering som förklarar hur det här värdet beräknades. Detta kan vara användbart om du vill visa extra resonemang i användargränssnittet. Det här fältet är användbart, till exempel när du anger resonemang från en LLM som genererade den här utvärderingen.
-
mått för godkänd/underkänd
Alla strängmått som returnerar "yes"
och "no"
behandlas som ett mått för pass/fail och har en särskild behandling i användargränssnittet.
Du kan också skapa ett mått för godkänd/underkänd med en anropsbar domare från Python SDK . Detta ger dig mer kontroll över vilka delar av spårningen som ska utvärderas och vilka förväntade fält som ska användas. Du kan använda någon av de inbyggda domarna för Mosaic AI-agentutvärdering. Se den inbyggda AI-domaren.
Exempel: Anpassade säkerhetsmått med vägledningsdomaren
Det här exemplet skapar två anpassade säkerhetsmått: svordomar och oförskämdhet. Den använder den anropbara guideline_adherence domaren.
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'])
numeriska mått
Numeriska mått utvärderar ordinalvärden, till exempel flyttal eller heltal. Numeriska mått visas i användargränssnittet per rad, tillsammans med det genomsnittliga värdet för utvärderingskörningen.
Exempel: svarslikhet
Det här måttet mäter likheten mellan response
och expected_response
med hjälp av det inbyggda Python-biblioteket 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'])
booleska mått
Booleska mått utvärderas till True
eller False
. Dessa är användbara för binära beslut, till exempel att kontrollera om ett svar uppfyller en enkel heuristisk. Om du vill att måttet ska ha en särskild pass/fail-behandling i användargränssnittet kan du läsa mått för pass/fail.
Exempel: språkmodellens självreferens
Det här måttet kontrollerar om svaret nämner "LLM" och returnerar True
om det gör det.
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'])
Använda custom_expected
Fältet custom_expected
kan användas för att överföra annan förväntad information till en anpassad mätning.
Exempel: Svarslängden är begränsad
Det här exemplet visar hur du kräver att längden på svaret ligger inom (min_length, max_length) gränser som angetts för varje exempel. Använd custom_expected
för att lagra information på radnivå som ska skickas till anpassade mått när du skapar en utvärdering.
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'])
Påståenden över spårningar
Anpassade mått kan utvärdera alla delar av en MLflow-spårning som skapats av agenten, inklusive intervall, attribut och utdata.
Exempel: Begär klassificeringsvägledning & routing
I det här exemplet skapas en agent som avgör om användarfrågan är en fråga eller en instruktion och returnerar den på vanlig engelska till användaren. I ett mer realistiskt scenario kan du använda den här tekniken för att dirigera olika frågor till olika funktioner.
Utvärderingsuppsättningen säkerställer att klassificeraren av frågetyp ger rätt resultat för en uppsättning indata med hjälp av anpassade mått som inspekterar MLFlow-spårningen.
I det här exemplet används MLflow-Trace.search_spans för att hitta intervall med typen KEYWORD
, som är en anpassad span-typ som du har definierat för den här agenten.
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'])
Genom att använda de här exemplen kan du utforma anpassade mått för att uppfylla dina unika utvärderingsbehov.
Utvärdera verktygsanrop
Anpassade mått tillhandahålls med tool_calls
som är en lista över ToolCallInvocation som ger dig information om vilka verktyg som anropades och vad de returnerade.
Exempel: Att hävda rätt verktyg kallas
Notera
Det här exemplet kan inte kopieras eftersom det inte definierar LangGraph-agenten. Se i den bifogade -notebooken för det fullständigt körbara exemplet.
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()
Utveckla anpassade mått
När du utvecklar mått måste du snabbt iterera måttet utan att behöva köra agenten varje gång du gör en ändring. Använd följande strategi för att göra detta enklare:
- Generera ett svarsblad från agenten för utvärderingsdatauppsättningar. Detta utför agenten för var och en av posterna i utvärderingsuppsättningen och genererar svar och loggar som du kan använda för att anropa måttet direkt.
- Definiera metrik.
- Anropa måttet för varje värde i svarsbladet direkt och iterera på måttdefinitionen.
- När måttet fungerar som förväntat kör du
mlflow.evaluate()
på samma svarsblad för att kontrollera att resultatet från agentutvärderingen är det du förväntar dig. Koden i det här exemplet använder inte fältetmodel=
, så utvärderingen använder förberäknade svar. - När du är nöjd med måttets prestanda aktiverar du fältet
model=
imlflow.evaluate()
för att anropa agenten interaktivt.
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'])
Exempelanteckningsbok
Följande notebook-exempel visar några olika sätt att använda anpassade mått i Mosaic AI Agent Evaluation.