66from typing import Any , Callable
77
88from galileo .__future__ .base import BusinessObjectMixin , SyncState
9+ from galileo .__future__ .configuration import Configuration
910from galileo .__future__ .exceptions import ValidationError
1011from galileo .metrics import Metrics
1112from galileo .resources .models import OutputTypeEnum , ScorerTypes
@@ -37,14 +38,11 @@ class BuiltInScorers:
3738
3839 def __getattr__ (self , name : str ) -> GalileoScorers :
3940 """Allow attribute-style access to built-in scorers."""
40- # Try to find the scorer by name
41+ # Try to find the scorer by name (enum names match UI-visible names)
4142 for scorer in GalileoScorers :
42- # Match against both enum name (UI-visible) and internal value
43- if scorer .name == name or scorer .value .lstrip ("_" ) == name :
43+ if scorer .name == name :
4444 return scorer
45- raise AttributeError (
46- f"Built-in scorer '{ name } ' not found. Available: { [s .name for s in GalileoScorers ]} "
47- )
45+ raise AttributeError (f"Built-in scorer '{ name } ' not found. Available: { [s .name for s in GalileoScorers ]} " )
4846
4947 def __dir__ (self ) -> list [str ]:
5048 """Return list of available scorer names for autocomplete."""
@@ -84,6 +82,12 @@ class Metric(BusinessObjectMixin):
8482 ----------------
8583 scorers (BuiltInScorers): Access built-in Galileo scorers.
8684
85+ Configuration
86+ -------------
87+ Default values for `model` and `judges` can be configured via:
88+ - Configuration.default_scorer_model (env: GALILEO_DEFAULT_SCORER_MODEL)
89+ - Configuration.default_scorer_judges (env: GALILEO_DEFAULT_SCORER_JUDGES)
90+
8791 Examples
8892 --------
8993 # 1. Use built-in scorers
@@ -142,7 +146,10 @@ def response_length_scorer(trace_or_span):
142146 # List all metrics
143147 metrics = Metric.list()
144148
145- # Delete a metric
149+ # Delete a metric (two ways)
150+ Metric.delete_by_name("old-metric") # Direct deletion without retrieval
151+ # OR
152+ metric = Metric.get(name="old-metric")
146153 metric.delete()
147154 """
148155
@@ -204,8 +211,8 @@ def __init__(
204211 Args:
205212 name: The name of the metric.
206213 prompt: Prompt template for LLM scorers (preferred over user_prompt).
207- model: Model name to use (preferred over model_name). Defaults to "gpt-4.1-mini" .
208- judges: Number of judges (preferred over num_judges). Defaults to 3 .
214+ model: Model name to use (preferred over model_name). Defaults to Configuration.default_scorer_model .
215+ judges: Number of judges (preferred over num_judges). Defaults to Configuration.default_scorer_judges .
209216 user_prompt: [Deprecated] Use 'prompt' instead.
210217 model_name: [Deprecated] Use 'model' instead.
211218 num_judges: [Deprecated] Use 'judges' instead.
@@ -231,8 +238,12 @@ def __init__(
231238
232239 # Handle parameter aliases (new names preferred)
233240 final_prompt = prompt or user_prompt
234- final_model = model or model_name or "gpt-4.1-mini"
235- final_judges = judges if judges is not None else (num_judges if num_judges is not None else 3 )
241+ final_model = model or model_name or Configuration .default_scorer_model
242+ final_judges = (
243+ judges
244+ if judges is not None
245+ else (num_judges if num_judges is not None else Configuration .default_scorer_judges )
246+ )
236247
237248 # Auto-detect scorer type
238249 if scorer_type is None :
@@ -340,8 +351,8 @@ def create(self) -> Metric:
340351 user_prompt = self .prompt or "" ,
341352 node_level = self .node_level or StepType .llm ,
342353 cot_enabled = self .cot_enabled or True ,
343- model_name = self .model or "gpt-4.1-mini" ,
344- num_judges = self .judges or 3 ,
354+ model_name = self .model or Configuration . default_scorer_model ,
355+ num_judges = self .judges or Configuration . default_scorer_judges ,
345356 description = self .description ,
346357 tags = self .tags ,
347358 output_type = self .output_type
@@ -459,6 +470,39 @@ def list(
459470
460471 return result
461472
473+ @classmethod
474+ def delete_by_name (cls , name : str ) -> None :
475+ """
476+ Delete a metric by name without retrieving it first.
477+
478+ This is more efficient than calling `Metric.get(name=...).delete()`
479+ when you only need to delete and don't need the metric object.
480+
481+ Args:
482+ name: The name of the metric to delete.
483+
484+ Raises
485+ ------
486+ ValueError: If no metric with the given name exists.
487+
488+ Examples
489+ --------
490+ # Delete without retrieving first
491+ Metric.delete_by_name("old-metric")
492+
493+ # Alternative (less efficient)
494+ metric = Metric.get(name="old-metric")
495+ metric.delete()
496+ """
497+ logger .info (f"Metric.delete_by_name: name='{ name } ' - started" )
498+ try :
499+ metrics_service = Metrics ()
500+ metrics_service .delete_metric (name = name )
501+ logger .info (f"Metric.delete_by_name: name='{ name } ' - completed" )
502+ except Exception as e :
503+ logger .error (f"Metric.delete_by_name: name='{ name } ' - failed: { e } " )
504+ raise
505+
462506 def _populate_from_scorer_response (self , scorer_response : Any ) -> None :
463507 """Populate instance attributes from a ScorerResponse object."""
464508 self .id = scorer_response .id
0 commit comments