Skip to content

Commit b9763f9

Browse files
elisnohuiwengoh
andauthored
Add support for skipping trustworthiness scoring (#102)
Co-authored-by: Hui Wen <45724323+huiwengoh@users.noreply.github.com>
1 parent 2816b08 commit b9763f9

File tree

8 files changed

+151
-3
lines changed

8 files changed

+151
-3
lines changed

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.1.23] - 2025-08-06
11+
12+
### Changed
13+
14+
- Updated `TLMOptions` to support `disable_trustworthiness` parameter
15+
- Skips trustworthiness scoring when `disable_trustworthiness` is True, assuming either custom evaluation criteria (TLM) or RAG Evals (TrustworthyRAG) are provided
16+
17+
1018
## [1.1.22] - 2025-07-29
1119

1220
### Added
@@ -291,7 +299,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
291299
- Release of the Cleanlab TLM Python client.
292300

293301

294-
[Unreleased]: https://github.com/cleanlab/cleanlab-tlm/compare/v1.1.22...HEAD
302+
[Unreleased]: https://github.com/cleanlab/cleanlab-tlm/compare/v1.1.23...HEAD
303+
[1.1.23]: https://github.com/cleanlab/cleanlab-tlm/compare/v1.1.22...v1.1.23
295304
[1.1.22]: https://github.com/cleanlab/cleanlab-tlm/compare/v1.1.21...v1.1.22
296305
[1.1.21]: https://github.com/cleanlab/cleanlab-tlm/compare/v1.1.20...v1.1.21
297306
[1.1.20]: https://github.com/cleanlab/cleanlab-tlm/compare/v1.1.19...v1.1.20

src/cleanlab_tlm/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# SPDX-License-Identifier: MIT
2-
__version__ = "1.1.22"
2+
__version__ = "1.1.23"

src/cleanlab_tlm/internal/validation.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
from __future__ import annotations
2+
13
import os
24
import warnings
35
from collections.abc import Sequence
4-
from typing import Any, Callable, Optional, Union
6+
from typing import TYPE_CHECKING, Any, Callable, Optional, Union
57

68
from cleanlab_tlm.errors import ValidationError
79
from cleanlab_tlm.internal.constants import (
@@ -24,6 +26,10 @@
2426
)
2527
from cleanlab_tlm.internal.types import Task
2628

29+
if TYPE_CHECKING:
30+
from cleanlab_tlm.tlm import TLMOptions
31+
from cleanlab_tlm.utils.rag import Eval
32+
2733
SKIP_VALIDATE_TLM_OPTIONS: bool = os.environ.get("CLEANLAB_TLM_SKIP_VALIDATE_TLM_OPTIONS", "false").lower() == "true"
2834

2935

@@ -198,6 +204,27 @@ def validate_tlm_options(
198204

199205
if not isinstance(criteria.get("criteria"), str):
200206
raise ValidationError(f"'criteria' in custom_eval_criteria item {i} must be a string.")
207+
elif option == "disable_trustworthiness":
208+
if not isinstance(val, bool):
209+
raise ValidationError(f"Invalid type {type(val)}, disable_trustworthiness must be a boolean")
210+
if val and support_custom_eval_criteria and not options.get("custom_eval_criteria"):
211+
raise ValidationError("disable_trustworthiness is only supported when custom_eval_criteria is provided")
212+
213+
214+
def _validate_trustworthy_rag_options(options: Optional[TLMOptions], initialized_evals: list[Eval]) -> None:
215+
"""To be used for ensuring TLMOptions are set correctly given other parameters to TrustworthyRAG
216+
217+
options: TLMOptions
218+
initialized_evals: list[Eval]
219+
The evals field configured in TrustworthyRAG.__init__. Required to validate disable_trustworthiness option.
220+
"""
221+
disable_trustworthiness = options and options.get("disable_trustworthiness", False)
222+
223+
if disable_trustworthiness and not initialized_evals:
224+
raise ValidationError(
225+
"When disable_trustworthiness=True in TrustworthyRAG, at least one evaluation must be provided. "
226+
"Either provide evaluations via the 'evals' parameter or set disable_trustworthiness=False."
227+
)
201228

202229

203230
def process_and_validate_kwargs_constrain_outputs(

src/cleanlab_tlm/tlm.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,12 +613,14 @@ class TLMOptions(TypedDict):
613613
num_self_reflections (int, default = 3): the number of different evaluations to perform where the LLM reflects on the response, a factor affecting trust scoring.
614614
The maximum number currently supported is 3. Lower values can reduce runtimes.
615615
Reflection helps quantify aleatoric uncertainty associated with challenging prompts and catches responses that are noticeably incorrect/bad upon further analysis.
616+
This parameter has no effect when `disable_trustworthiness` is True.
616617
617618
num_consistency_samples (int, default = 8): the amount of internal sampling to measure LLM response consistency, a factor affecting trust scoring.
618619
Must be between 0 and 20. Lower values can reduce runtimes.
619620
Measuring consistency helps quantify the epistemic uncertainty associated with
620621
strange prompts or prompts that are too vague/open-ended to receive a clearly defined 'good' response.
621622
TLM measures consistency via the degree of contradiction between sampled responses that the model considers plausible.
623+
This parameter has no effect when `disable_trustworthiness` is True.
622624
623625
similarity_measure ({"semantic", "string", "embedding", "embedding_large", "code", "discrepancy"}, default = "discrepancy"): how the
624626
trustworthiness scoring's consistency algorithm measures similarity between alternative responses considered plausible by the model.
@@ -633,6 +635,11 @@ class TLMOptions(TypedDict):
633635
You can auto-improve responses by increasing this parameter, but at higher runtimes/costs.
634636
This parameter must be between 1 and 20. It has no effect on `TLM.score()`.
635637
When this parameter is 1, `TLM.prompt()` simply returns a standard LLM response and does not attempt to auto-improve it.
638+
This parameter has no effect when `disable_trustworthiness` is True.
639+
640+
disable_trustworthiness (bool, default = False): if True, trustworthiness scoring is disabled and TLM will not compute trust scores for responses.
641+
This is useful when you only want to use custom evaluation criteria or when you want to minimize computational overhead and only need the base LLM response.
642+
The following parameters will be ignored when `disable_trustworthiness` is True: `num_consistency_samples`, `num_self_reflections`, `num_candidate_responses`, `reasoning_effort`, `similarity_measure`.
636643
"""
637644

638645
model: NotRequired[str]
@@ -645,3 +652,4 @@ class TLMOptions(TypedDict):
645652
reasoning_effort: NotRequired[str]
646653
log: NotRequired[list[str]]
647654
custom_eval_criteria: NotRequired[list[dict[str, Any]]]
655+
disable_trustworthiness: NotRequired[bool]

src/cleanlab_tlm/utils/rag.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
)
4343
from cleanlab_tlm.internal.exception_handling import handle_tlm_exceptions
4444
from cleanlab_tlm.internal.validation import (
45+
_validate_trustworthy_rag_options,
4546
tlm_score_process_response_and_kwargs,
4647
validate_rag_inputs,
4748
)
@@ -75,6 +76,7 @@ class TrustworthyRAG(BaseTLM):
7576
7677
options ([TLMOptions](../tlm/#class-tlmoptions), optional): a typed dict of advanced configurations you can optionally specify.
7778
The "custom_eval_criteria" key for [TLM](../tlm/#class-tlm) is not supported for `TrustworthyRAG`, you can instead specify `evals`.
79+
The "disable_trustworthiness" key is only supported for `TrustworthyRAG` when it's set to run `Evals`. See the `evals` argument description below for how evaluations are determined.
7880
7981
timeout (float, optional): timeout (in seconds) to apply to each request.
8082
@@ -131,6 +133,8 @@ def __init__(
131133

132134
self._evals = evals
133135

136+
_validate_trustworthy_rag_options(options=options, initialized_evals=self._evals)
137+
134138
def score(
135139
self,
136140
*,

tests/test_get_trustworthiness_score.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,26 @@ def reset_tlm(tlm: TLM) -> Generator[None, None, None]:
203203
original_timeout = tlm._timeout
204204
yield
205205
tlm._timeout = original_timeout
206+
207+
208+
def test_get_trustworthiness_score_with_disable_trustworthiness(tlm_api_key: str) -> None:
209+
"""Tests get_trustworthiness_score with disable_trustworthiness option.
210+
211+
When disable_trustworthiness is enabled (along with custom_eval_criteria),
212+
the trustworthiness_score should be None in the response.
213+
214+
Expected:
215+
- TLM should return a response
216+
- trustworthiness_score should be None
217+
- No exceptions are raised
218+
"""
219+
tlm = TLM(
220+
api_key=tlm_api_key,
221+
options={
222+
"disable_trustworthiness": True,
223+
"custom_eval_criteria": [{"name": "test", "criteria": "test criteria"}],
224+
},
225+
)
226+
response = tlm.get_trustworthiness_score(test_prompt, TEST_RESPONSE)
227+
assert not isinstance(response, list)
228+
assert response["trustworthiness_score"] is None

tests/test_tlm_rag.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,3 +962,30 @@ def reset_rag_timeout(trustworthy_rag: TrustworthyRAG) -> Generator[None, None,
962962
old_timeout = trustworthy_rag._timeout
963963
yield
964964
trustworthy_rag._timeout = old_timeout
965+
966+
967+
def test_score_with_disable_trustworthiness(trustworthy_rag_api_key: str) -> None:
968+
"""Tests score with disable_trustworthiness option.
969+
970+
When disable_trustworthiness is enabled (along with valid evals),
971+
the trustworthiness score should be None in the response.
972+
973+
Expected:
974+
- TrustworthyRAG should return a response
975+
- response should have the trustworthiness key
976+
- trustworthiness score should be None
977+
- No exceptions are raised
978+
"""
979+
trustworthy_rag = TrustworthyRAG(
980+
api_key=trustworthy_rag_api_key,
981+
options={"disable_trustworthiness": True},
982+
)
983+
response = trustworthy_rag.score(
984+
query=test_query,
985+
context=test_context,
986+
response=test_response,
987+
prompt=test_prompt,
988+
)
989+
assert not isinstance(response, list)
990+
assert "trustworthiness" in response
991+
assert response["trustworthiness"]["score"] is None

tests/test_validation.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,22 @@ def test_validate_tlm_options_support_custom_eval_criteria() -> None:
687687
):
688688
validate_tlm_options(options, support_custom_eval_criteria=False)
689689

690+
# Valid with disable_trustworthiness=True and custom_eval_criteria
691+
validate_tlm_options({**options, "disable_trustworthiness": True}, support_custom_eval_criteria=True)
692+
693+
# Invalid: disable_trustworthiness=True without custom_eval_criteria
694+
with pytest.raises(
695+
ValidationError, match="^disable_trustworthiness is only supported when custom_eval_criteria is provided"
696+
):
697+
validate_tlm_options({"disable_trustworthiness": True}, support_custom_eval_criteria=True)
698+
699+
with pytest.raises(
700+
ValidationError, match="^disable_trustworthiness is only supported when custom_eval_criteria is provided"
701+
):
702+
validate_tlm_options(
703+
{"disable_trustworthiness": True, "custom_eval_criteria": None}, support_custom_eval_criteria=True
704+
)
705+
690706

691707
def test_validate_rag_inputs_mixed_string_and_sequence() -> None:
692708
"""Tests that validate_rag_inputs rejects mixed inputs where some are strings and others are sequences."""
@@ -798,3 +814,37 @@ def test_validate_rag_inputs_matching_lists() -> None:
798814
assert len(result) == list_length
799815
assert result[0] == "Q: query 1 C: context 1"
800816
assert result[1] == "Q: query 2 C: context 2"
817+
818+
819+
def test_disable_trustworthiness_without_custom_criteria_raises_error(tlm_api_key: str) -> None:
820+
"""Test that disable_trustworthiness=True without custom_eval_criteria raises ValueError."""
821+
with pytest.raises(
822+
ValidationError, match="^disable_trustworthiness is only supported when custom_eval_criteria is provided"
823+
):
824+
TLM(api_key=tlm_api_key, options={"disable_trustworthiness": True})
825+
826+
827+
def test_disable_trustworthiness_with_custom_criteria_works(tlm_api_key: str) -> None:
828+
"""Test that disable_trustworthiness=True with custom_eval_criteria works normally."""
829+
TLM(
830+
api_key=tlm_api_key,
831+
options={
832+
"disable_trustworthiness": True,
833+
"custom_eval_criteria": [{"name": "test", "criteria": "test criteria"}],
834+
},
835+
)
836+
837+
838+
def test_disable_trustworthiness_without_custom_criteria_raises_error_rag(tlm_api_key: str) -> None:
839+
"""Test that disable_trustworthiness=True without custom_eval_criteria raises ValueError for TrustworthyRAG."""
840+
from cleanlab_tlm.utils.rag import TrustworthyRAG
841+
842+
with pytest.raises(ValidationError, match="^When disable_trustworthiness=True in TrustworthyRAG"):
843+
TrustworthyRAG(evals=[], api_key=tlm_api_key, options={"disable_trustworthiness": True})
844+
845+
846+
def test_disable_trustworthiness_with_custom_criteria_works_rag(tlm_api_key: str) -> None:
847+
"""Test that disable_trustworthiness=True with custom_eval_criteria works normally for TrustworthyRAG."""
848+
from cleanlab_tlm.utils.rag import TrustworthyRAG
849+
850+
TrustworthyRAG(api_key=tlm_api_key, options={"disable_trustworthiness": True})

0 commit comments

Comments
 (0)