Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions run.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ providers:
- provider_id: vllm
provider_type: remote::vllm
config:
url: ${env.VLLM_URL:http://localhost:8000/v1}
url: ${env.VLLM_URL:=}
max_tokens: ${env.VLLM_MAX_TOKENS:4096}
api_token: ${env.VLLM_API_TOKEN:fake}
tls_verify: ${env.VLLM_TLS_VERIFY:true}
eval:
- provider_id: trustyai_lmeval
provider_type: remote::trustyai_lmeval
config:
use_k8s: True
base_url: ${env.VLLM_URL:http://localhost:8000/v1}
use_k8s: ${env.TRUSTYAI_LMEVAL_USE_K8S:=true}
base_url: ${env.VLLM_URL:=}
namespace: ${env.TRUSTYAI_LM_EVAL_NAMESPACE}
external_providers_dir: ./providers.d
4 changes: 0 additions & 4 deletions src/llama_stack_provider_lmeval/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,6 @@ def __post_init__(self):
"""Validate the configuration"""
if not isinstance(self.use_k8s, bool):
raise LMEvalConfigError("use_k8s must be a boolean")
if self.use_k8s is False:
raise LMEvalConfigError(
Comment on lines -133 to -134
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Removing the check for use_k8s disables early error reporting for unsupported backends.

This change may result in less informative error messages, as misconfigured backends will fail later at runtime instead of during configuration validation.

"Only Kubernetes LMEval backend is supported at the moment"
)


__all__ = [
Expand Down
40 changes: 32 additions & 8 deletions src/llama_stack_provider_lmeval/lmeval.py
Original file line number Diff line number Diff line change
Expand Up @@ -923,27 +923,40 @@ class LMEval(Eval, BenchmarksProtocolPrivate):

def __init__(self, config: LMEvalEvalProviderConfig):
self._config = config
self._namespace: str | None = None

self._namespace = _resolve_namespace(self._config)

logger.debug("LMEval provider initialized with namespace: %s", self._namespace)
logger.debug("LMEval provider config values: %s", vars(self._config))
self.benchmarks: dict[str, Benchmark] = {}
self._jobs: list[Job] = []
self._job_metadata: dict[str, dict[str, Any]] = {}

self._k8s_client: k8s_client.ApiClient | None = None
self._k8s_custom_api: k8s_client.CustomObjectsApi | None = None
if self.use_k8s:
self._cr_builder: LMEvalCRBuilder | None = None

def _ensure_k8s_initialized(self):
"""Ensure Kubernetes client and namespace are initialized when needed."""
if not self.use_k8s:
logger.warning("Non-K8s evaluation backend is not implemented yet")
Comment on lines +939 to +940
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Logging a warning for non-K8s backend may be redundant given the subsequent NotImplementedError.

Consider removing the warning in _ensure_k8s_initialized, as NotImplementedError is raised elsewhere if use_k8s is False. Alternatively, update the warning to clarify where the error will occur.

Suggested implementation:

    def _ensure_k8s_initialized(self):
        """Ensure Kubernetes client and namespace are initialized when needed."""
        if not self.use_k8s:
            return

If you want to clarify in the log that the error will be raised elsewhere, you could replace the warning with:

logger.warning("use_k8s is False; NotImplementedError will be raised in subsequent calls.")

But the cleanest approach is simply to remove the warning as shown above.

return

if self._k8s_client is None:
self._init_k8s_client()
logger.debug(
"Initialized Kubernetes client with namespace: %s", self._namespace
)

if self._namespace is None:
self._namespace = _resolve_namespace(self._config)
logger.debug("LMEval provider resolved namespace: %s", self._namespace)

if self._cr_builder is None:
self._cr_builder = LMEvalCRBuilder(
namespace=self._namespace,
service_account=getattr(self._config, "service_account", None),
)
self._cr_builder._config = self._config
logger.debug(
"Initialized Kubernetes client and CR builder with namespace: %s",
self._namespace,
)

def _init_k8s_client(self):
"""Initialize the Kubernetes client."""
Expand Down Expand Up @@ -1048,7 +1061,8 @@ def _deploy_lmeval_cr(self, cr: dict, job_id: str) -> None:
pvc_name = None

if (
self._cr_builder._config is not None
self._cr_builder is not None
and self._cr_builder._config is not None
and hasattr(self._cr_builder._config, "metadata")
and self._cr_builder._config.metadata
):
Expand Down Expand Up @@ -1198,6 +1212,7 @@ async def run_eval(
Returns:
Dict containing job_id for evaluation tracking
"""
self._ensure_k8s_initialized()
if not self.use_k8s:
raise NotImplementedError("Non-K8s evaluation not implemented yet")

Expand All @@ -1224,6 +1239,11 @@ async def run_eval(
benchmark_config.metadata["input"]["storage"],
)

if self._cr_builder is None:
raise LMEvalConfigError(
"CR builder not initialized - ensure K8s is properly configured"
)

cr = self._cr_builder.create_cr(
benchmark_id=benchmark_id,
task_config=benchmark_config,
Expand Down Expand Up @@ -1295,6 +1315,7 @@ async def evaluate_rows(
Returns:
EvaluateResponse: Object containing generations and scores
"""
self._ensure_k8s_initialized()
if not self.use_k8s:
raise NotImplementedError("Non-K8s evaluation not implemented yet")

Expand Down Expand Up @@ -1323,6 +1344,7 @@ async def job_status(self, benchmark_id: str, job_id: str) -> dict[str, str] | N
Returns:
Dict with current status of the job
"""
self._ensure_k8s_initialized()
if not self.use_k8s:
raise NotImplementedError("Non-K8s evaluation not implemented yet")

Expand Down Expand Up @@ -1395,6 +1417,7 @@ async def job_cancel(self, benchmark_id: str, job_id: str) -> None:
benchmark_id: The benchmark identifier
job_id: The job identifier
"""
self._ensure_k8s_initialized()
if not self.use_k8s:
raise NotImplementedError("Non-K8s evaluation not implemented yet")

Expand Down Expand Up @@ -1568,6 +1591,7 @@ async def job_result(self, benchmark_id: str, job_id: str) -> EvaluateResponse:
Returns:
EvaluateResponse: Results of the evaluation
"""
self._ensure_k8s_initialized()
if not self.use_k8s:
return EvaluateResponse(
generations=[],
Expand Down
Loading