Code-Evals
Create custom metrics using Python code on Confident AI
Overview
Code-Eval lets you create and execute custom metrics by writing Python code directly on the Confident AI platform. Unlike G-Eval which uses natural language criteria, Code-Eval gives you full programmatic control over your evaluation logic using the deepeval framework.
Why Code-Eval?
Code-Eval is ideal when you need evaluation logic that can't be expressed in natural language:
- Exact format validation — Verify JSON structure, regex patterns, or specific output formats
- Deterministic scoring — Apply consistent, rule-based logic without LLM variability
- Complex calculations — Perform multi-step computations, statistical analysis, or aggregations
- Custom business rules — Implement domain-specific validation logic unique to your use case
How It Works
Code-Eval works exactly like creating a custom metric in deepeval. You write a Python class that inherits from BaseMetric and implement the evaluation logic.
However, on Confident AI you can only edit the following methods:
a_measure()— the async method where your evaluation logic runsis_successful()— determines whether the test case passed
All other parts of the metric (initialization, properties, etc.) are handled by the platform.
Available Packages
Your code runs in a secure environment with access to:
deepevallibrary — Always the latest version from GitHub, including all utilities likeBaseMetric, and test case types- Standard Python libraries —
json,re,math,collections,datetime, etc. - No external network calls — For security reasons, external API calls are not supported (for now)
Create Code-Eval via the UI
Code-Eval metrics can be created under Project > Metrics > Library.
Fill in metric details
Provide the metric name, and optionally a description. You can also toggle whether you're creating a single-turn or multi-turn metric.
General Metric Info Write your evaluation code
Instead of defining criteria, evaluation steps, and rubrics like in G-Eval, you write Python code that computes the evaluation score directly.
Your code must inherit from the appropriate base class and implement:
a_measure(test_case)— Your async evaluation logic that setsself.score,self.reason, andself.successis_successful()— Returns whether the metric passed based on the threshold (pre-filled for you, not recommended to change)
You
a_measure()method does not have to returnself.score- although it is recommended that you do so.For single-turn metrics, inherit from
BaseMetricand accept anLLMTestCase:from deepeval.metrics import BaseMetric from deepeval.test_case import LLMTestCase class CodeMetric(BaseMetric): async def a_measure(self, test_case: LLMTestCase) -> float: # Your evaluation logic here if len(test_case.actual_output) > 5: self.score = 1 else: self.score = 0 self.success = self.score >= self.threshold return self.score def is_successful(self) -> bool: if self.error is not None: self.success = False else: try: self.success = self.score >= self.threshold except TypeError: self.success = False return self.successThe
LLMTestCaseobject gives you access to parameters such asinput,actual_output,expected_output, and more.For multi-turn metrics, inherit from
BaseConversationalMetricand accept aConversationalTestCase:from deepeval.metrics import BaseConversationalMetric from deepeval.test_case import ConversationalTestCase class CodeMetric(BaseConversationalMetric): async def a_measure(self, test_case: ConversationalTestCase) -> float: # Your evaluation logic here if len(test_case.turns) > 5: self.score = 1 else: self.score = 0 self.success = self.score >= self.threshold return self.score def is_successful(self) -> bool: if self.error is not None: self.success = False else: try: self.success = self.score >= self.threshold except TypeError: self.success = False return self.successThe
ConversationalTestCasegives you access to a list ofturns, where each turn containsrole,content, and other parameters.Review and save
Once you've written your code, make sure everything looks right in the final review page, and click Save.
Advanced Usage
Set verbose logs
Use self.verbose_logs to log intermediate steps and decision paths in your evaluation logic. This is useful for debugging complex metrics and understanding how scores are computed.
from deepeval.metrics import BaseMetric
from deepeval.test_case import LLMTestCase
class CodeMetric(BaseMetric):
async def a_measure(self, test_case: LLMTestCase) -> float:
# Log anything for debugging purposes
self.verbose_logs = "Wow I can't believe I can do this on Confident AI"
return self.score
def is_successful(self) -> bool:
if self.error is not None:
self.success = False
return self.successLog reasoning
Use self.reason to provide a human-readable explanation of the score. This helps users understand why a particular score was given and is displayed in the evaluation results.
from deepeval.metrics import BaseMetric
from deepeval.test_case import LLMTestCase
class CodeMetric(BaseMetric):
async def a_measure(self, test_case: LLMTestCase) -> float:
# Set any reason you wish
self.reason = "Wow I can't believe I can do this on Confident AI"
return self.score
def is_successful(self) -> bool:
if self.error is not None:
self.success = False
return self.successRaise exceptions
You can also raise an error like how you would normally do so in Python and log it to self.error:
from deepeval.metrics import BaseMetric
from deepeval.test_case import LLMTestCase
class CodeMetric(BaseMetric):
async def a_measure(self, test_case: LLMTestCase) -> float:
try:
raise ValueError("Raising an error because I feel like it")
except Exception as e:
# Surface the error before re-raising
self.error = str(e)
raise
return self.score
def is_successful(self) -> bool:
if self.error is not None:
self.success = False
return self.success