Files
mlflow--mlflow/tests/openai/test_openai_evaluate.py
2026-07-13 13:22:34 +08:00

138 lines
3.9 KiB
Python

from unittest import mock
import openai
import pandas as pd
import pytest
import mlflow
from mlflow.models.evaluation import evaluate
from mlflow.tracing.constant import TraceMetadataKey
from tests.tracing.helper import get_traces, purge_traces, reset_autolog_state # noqa: F401
_EVAL_DATA = pd.DataFrame({
"inputs": [
"What is MLflow?",
"What is Spark?",
],
"ground_truth": [
"MLflow is an open-source platform to manage the ML lifecycle.",
"Spark is a unified analytics engine for big data processing.",
],
})
@pytest.fixture
def client(monkeypatch, mock_openai):
monkeypatch.setenv("OPENAI_API_KEY", "test")
monkeypatch.setenv("OPENAI_API_BASE", mock_openai)
return openai.OpenAI(api_key="test", base_url=mock_openai)
@pytest.mark.parametrize(
"config",
[
None,
{"log_traces": False},
{"log_traces": True},
],
)
@pytest.mark.usefixtures("reset_autolog_state")
def test_openai_evaluate(client, config):
if config:
mlflow.openai.autolog(**config)
is_trace_disabled = config and not config.get("log_traces", True)
is_trace_enabled = config and config.get("log_traces", True)
def model(inputs):
return [
client.chat.completions
.create(
messages=[{"role": "user", "content": question}],
model="gpt-4o-mini",
temperature=0.0,
)
.choices[0]
.message.content
for question in inputs["inputs"]
]
with mock.patch("mlflow.openai.log_model") as log_model_mock:
with mlflow.start_run() as run:
evaluate(
model,
data=_EVAL_DATA,
targets="ground_truth",
extra_metrics=[mlflow.metrics.exact_match()],
)
log_model_mock.assert_not_called()
# Traces should not be logged when disabled explicitly
if is_trace_disabled:
assert len(get_traces()) == 0
else:
assert len(get_traces()) == 2
assert run.info.run_id == get_traces()[0].info.request_metadata[TraceMetadataKey.SOURCE_RUN]
purge_traces()
# Test original autolog configs is restored
client.chat.completions.create(
messages=[{"role": "user", "content": "hi"}], model="gpt-4o-mini"
)
assert len(get_traces()) == (1 if is_trace_enabled else 0)
@pytest.mark.usefixtures("reset_autolog_state")
def test_openai_pyfunc_evaluate(client):
with mlflow.start_run() as run:
model_info = mlflow.openai.log_model(
"gpt-4o-mini",
"chat.completions",
name="model",
messages=[{"role": "system", "content": "You are an MLflow expert."}],
)
evaluate(
model_info.model_uri,
data=_EVAL_DATA,
targets="ground_truth",
extra_metrics=[mlflow.metrics.exact_match()],
)
assert len(get_traces()) == 2
assert run.info.run_id == get_traces()[0].info.request_metadata[TraceMetadataKey.SOURCE_RUN]
@pytest.mark.parametrize("globally_disabled", [True, False])
@pytest.mark.usefixtures("reset_autolog_state")
def test_openai_evaluate_should_not_log_traces_when_disabled(client, globally_disabled):
if globally_disabled:
mlflow.autolog(disable=True)
else:
mlflow.openai.autolog(disable=True)
def model(inputs):
return [
client.chat.completions
.create(
messages=[{"role": "user", "content": question}],
model="gpt-4o-mini",
temperature=0.0,
)
.choices[0]
.message.content
for question in inputs["inputs"]
]
with mlflow.start_run():
evaluate(
model,
data=_EVAL_DATA,
targets="ground_truth",
extra_metrics=[mlflow.metrics.exact_match()],
)
assert len(get_traces()) == 0