switch-trust-cli 1.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- switch_trust/__init__.py +0 -0
- switch_trust/cli/__init__.py +0 -0
- switch_trust/cli/__main__.py +3 -0
- switch_trust/cli/builtin_config.json +879 -0
- switch_trust/cli/console.py +127 -0
- switch_trust/cli/eval_cli.py +905 -0
- switch_trust/cli/file_filter.py +172 -0
- switch_trust/cli/init_cli.py +156 -0
- switch_trust/cli/main.py +384 -0
- switch_trust/cli/output_formatters.py +482 -0
- switch_trust/cli/rich_observer.py +89 -0
- switch_trust/cli/runner.py +274 -0
- switch_trust/cli/scan_cli.py +314 -0
- switch_trust/cli/telemetry.py +430 -0
- switch_trust/cli/utils.py +158 -0
- switch_trust/cli/version.py +1 -0
- switch_trust/data/detector_prompts/llm01_adversarial.txt +59 -0
- switch_trust/data/detector_prompts/llm01_fixed.txt +6 -0
- switch_trust/data/detector_prompts/llm02_adversarial.txt +79 -0
- switch_trust/data/detector_prompts/llm02_fixed.txt +6 -0
- switch_trust/data/detector_prompts/llm05_adversarial.txt +67 -0
- switch_trust/data/detector_prompts/llm05_fixed.txt +14 -0
- switch_trust/data/detector_prompts/llm06_adversarial.txt +139 -0
- switch_trust/data/detector_prompts/llm06_fixed.txt +13 -0
- switch_trust/data/detector_prompts/llm07_adversarial.txt +189 -0
- switch_trust/data/detector_prompts/llm07_fixed.txt +12 -0
- switch_trust/data/detector_prompts/llm09_adversarial.txt +83 -0
- switch_trust/data/detector_prompts/llm09_fixed.txt +13 -0
- switch_trust/data/llm01_prompt_injection.csv +6708 -0
- switch_trust/data/llm02_sensitive_information.csv +1069 -0
- switch_trust/data/llm05_unsafe_output.csv +3882 -0
- switch_trust/data/llm06_excessive_agency.csv +778 -0
- switch_trust/data/llm07_system_prompt_leakage.csv +971 -0
- switch_trust/data/llm09_hallucination-goals.csv +32419 -0
- switch_trust/data/llm09_hallucination.csv +599 -0
- switch_trust/data/pii_leakage.csv +706 -0
- switch_trust/data/secret_leakage.csv +1380 -0
- switch_trust/eval/__init__.py +0 -0
- switch_trust/eval/common/__init__.py +0 -0
- switch_trust/eval/common/converter_anthropic.py +172 -0
- switch_trust/eval/common/converter_genai.py +171 -0
- switch_trust/eval/common/converter_openai.py +198 -0
- switch_trust/eval/common/log.py +116 -0
- switch_trust/eval/common/reference.py +25 -0
- switch_trust/eval/common/schema.py +190 -0
- switch_trust/eval/common/utils.py +119 -0
- switch_trust/eval/core/__init__.py +0 -0
- switch_trust/eval/core/detectors/__init__.py +0 -0
- switch_trust/eval/core/detectors/detector.py +25 -0
- switch_trust/eval/core/detectors/detector_garak.py +112 -0
- switch_trust/eval/core/detectors/detector_model.py +123 -0
- switch_trust/eval/core/detectors/detector_model_adversarial.py +91 -0
- switch_trust/eval/core/detectors/detector_pii.py +67 -0
- switch_trust/eval/core/detectors/detector_secret.py +88 -0
- switch_trust/eval/core/detectors/detector_topic_guard.py +63 -0
- switch_trust/eval/core/detectors/detector_toxicity.py +78 -0
- switch_trust/eval/core/eval/__init__.py +0 -0
- switch_trust/eval/core/eval/eval_creator.py +166 -0
- switch_trust/eval/core/eval/evaluation.py +112 -0
- switch_trust/eval/core/eval/evaluation_adversarial.py +412 -0
- switch_trust/eval/core/eval/evaluation_garak_module.py +45 -0
- switch_trust/eval/core/eval/evaluation_garak_probe.py +308 -0
- switch_trust/eval/core/eval/evaluation_message_list.py +46 -0
- switch_trust/eval/core/eval/evaluation_multi.py +276 -0
- switch_trust/eval/core/eval/evaluation_single.py +89 -0
- switch_trust/eval/core/eval/evaluation_single_prompt.py +62 -0
- switch_trust/eval/core/eval/evaluation_topic_guard.py +305 -0
- switch_trust/eval/core/eval/metric_conciseness.py +179 -0
- switch_trust/eval/core/eval/metric_factual_accuracy.py +312 -0
- switch_trust/eval/core/eval/metric_instruction_adherence.py +177 -0
- switch_trust/eval/core/eval/metric_tone.py +180 -0
- switch_trust/eval/core/eval/metric_toxicity.py +146 -0
- switch_trust/eval/core/eval/observer.py +137 -0
- switch_trust/eval/core/message/__init__.py +0 -0
- switch_trust/eval/core/message/message_collection.py +37 -0
- switch_trust/eval/core/message/message_collection_csv.py +44 -0
- switch_trust/eval/core/message/message_collection_garak.py +46 -0
- switch_trust/eval/core/message/message_collection_memory.py +34 -0
- switch_trust/eval/core/models/__init__.py +0 -0
- switch_trust/eval/core/models/generator_model.py +421 -0
- switch_trust/eval/core/models/model.py +172 -0
- switch_trust/eval/core/models/model_adk.py +186 -0
- switch_trust/eval/core/models/model_anthropic.py +79 -0
- switch_trust/eval/core/models/model_anthropic_agent.py +104 -0
- switch_trust/eval/core/models/model_gemini.py +146 -0
- switch_trust/eval/core/models/model_generic_http.py +120 -0
- switch_trust/eval/core/models/model_http.py +135 -0
- switch_trust/eval/core/models/model_huggingface.py +75 -0
- switch_trust/eval/core/models/model_langserve.py +96 -0
- switch_trust/eval/core/models/model_litellm.py +52 -0
- switch_trust/eval/core/models/model_ollama.py +65 -0
- switch_trust/eval/core/models/model_openai.py +71 -0
- switch_trust/eval/core/models/model_openai_agent.py +92 -0
- switch_trust/eval/core/models/model_openai_compatible.py +66 -0
- switch_trust/eval/core/models/model_per_endpoint_limiter.py +80 -0
- switch_trust/eval/core/models/model_retry.py +204 -0
- switch_trust/eval/core/models/model_sync_wrapper.py +38 -0
- switch_trust/eval/core/models/model_vertex_agent_runtime.py +315 -0
- switch_trust/eval/core/models/response_schema.py +148 -0
- switch_trust/eval/core/optional_deps.py +57 -0
- switch_trust/eval/db/__init__.py +0 -0
- switch_trust/eval/db/base/__init__.py +0 -0
- switch_trust/eval/db/base/common_types.py +16 -0
- switch_trust/eval/db/base/detectors/__init__.py +0 -0
- switch_trust/eval/db/base/detectors/detector_helpers.py +88 -0
- switch_trust/eval/db/base/detectors/detector_repository.py +96 -0
- switch_trust/eval/db/base/detectors/detector_types.py +77 -0
- switch_trust/eval/db/base/eval/__init__.py +0 -0
- switch_trust/eval/db/base/eval/eval_helpers.py +186 -0
- switch_trust/eval/db/base/eval/eval_repository.py +120 -0
- switch_trust/eval/db/base/eval/eval_run.py +142 -0
- switch_trust/eval/db/base/eval/eval_types.py +127 -0
- switch_trust/eval/db/base/eval/model_eval_repository.py +79 -0
- switch_trust/eval/db/base/eval/model_eval_run_repository.py +72 -0
- switch_trust/eval/db/base/eval/model_eval_run_result_repository.py +42 -0
- switch_trust/eval/db/base/eval/model_eval_run_result_types.py +21 -0
- switch_trust/eval/db/base/eval/model_eval_run_types.py +78 -0
- switch_trust/eval/db/base/eval/model_eval_types.py +69 -0
- switch_trust/eval/db/base/message/__init__.py +0 -0
- switch_trust/eval/db/base/message/message_collection_helpers.py +50 -0
- switch_trust/eval/db/base/message/message_collection_repository.py +95 -0
- switch_trust/eval/db/base/message/message_collection_types.py +87 -0
- switch_trust/eval/db/base/models/__init__.py +0 -0
- switch_trust/eval/db/base/models/model_helpers.py +253 -0
- switch_trust/eval/db/base/models/model_repository.py +104 -0
- switch_trust/eval/db/base/models/model_types.py +159 -0
- switch_trust/eval/db/json/__init__.py +0 -0
- switch_trust/eval/db/json/repository_json.py +559 -0
- switch_trust/scan/__init__.py +12 -0
- switch_trust/scan/agent_scanner.py +812 -0
- switch_trust/scan/config/agent_opengrep_rules.yaml +533 -0
- switch_trust/scan/config/agent_taxonomy.json +517 -0
- switch_trust/scan/config/agentic_cvss_mapping.yaml +136 -0
- switch_trust/scan/config/compliance_mappings.json +110 -0
- switch_trust/scan/config/triage_prompt.txt +326 -0
- switch_trust/scan/constants.py +15 -0
- switch_trust/scan/exception_classification.py +179 -0
- switch_trust/scan/llm_provider.py +330 -0
- switch_trust/scan/opengrep_resolver.py +12 -0
- switch_trust/scan/reasoner.py +602 -0
- switch_trust/scan/schema.py +315 -0
- switch_trust/scan/scorer.py +372 -0
- switch_trust/scan/static_scanner.py +681 -0
- switch_trust/scan/taxonomy.py +121 -0
- switch_trust/scan/tool_dispatcher.py +773 -0
- switch_trust/scan/trace_logger.py +118 -0
- switch_trust/scan/trace_logger_file.py +143 -0
- switch_trust/scan/trace_logger_log.py +100 -0
- switch_trust/scan/triage.py +614 -0
- switch_trust/schema.py +79 -0
- switch_trust/secret_anonymizer.py +72 -0
- switch_trust_cli-1.7.0.dist-info/METADATA +495 -0
- switch_trust_cli-1.7.0.dist-info/RECORD +157 -0
- switch_trust_cli-1.7.0.dist-info/WHEEL +5 -0
- switch_trust_cli-1.7.0.dist-info/entry_points.txt +2 -0
- switch_trust_cli-1.7.0.dist-info/licenses/LICENSE +210 -0
- switch_trust_cli-1.7.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Abstract interface for a repository of Evaluations.
|
|
3
|
+
|
|
4
|
+
An EvaluationRepository manages evaluation configurations,
|
|
5
|
+
providing CRUD operations over them. Evaluations are
|
|
6
|
+
always referenced by ID.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
|
|
13
|
+
from switch_trust.eval.core.eval.evaluation import Evaluation
|
|
14
|
+
from switch_trust.eval.db.base.detectors.detector_repository import DetectorRepository
|
|
15
|
+
from switch_trust.eval.db.base.eval.eval_types import (
|
|
16
|
+
DbEvaluation,
|
|
17
|
+
EvaluationListView,
|
|
18
|
+
EvaluationSortOrder,
|
|
19
|
+
)
|
|
20
|
+
from switch_trust.eval.db.base.message.message_collection_repository import (
|
|
21
|
+
MessageCollectionRepository,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class EvaluationRepository(ABC):
|
|
26
|
+
"""Repository that manages Evaluation configurations."""
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def list(self) -> list[DbEvaluation]:
|
|
30
|
+
"""Return all evaluation configurations in the repository."""
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def search(
|
|
35
|
+
self,
|
|
36
|
+
query: str | None = None,
|
|
37
|
+
types: list[str] | None = None,
|
|
38
|
+
order: EvaluationSortOrder | None = None,
|
|
39
|
+
offset: int = 0,
|
|
40
|
+
limit: int = 50,
|
|
41
|
+
) -> EvaluationListView:
|
|
42
|
+
"""Search evaluations by name with offset-based pagination.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
query: Text to match against the evaluation name
|
|
46
|
+
(case-insensitive substring match).
|
|
47
|
+
order: Sort field and direction.
|
|
48
|
+
offset: Number of items to skip.
|
|
49
|
+
limit: Maximum number of items to return.
|
|
50
|
+
"""
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def get(self, id: str) -> DbEvaluation:
|
|
55
|
+
"""Return the evaluation configuration with the given id.
|
|
56
|
+
|
|
57
|
+
Raises KeyError if the evaluation does not exist.
|
|
58
|
+
"""
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def create(
|
|
63
|
+
self,
|
|
64
|
+
config: DbEvaluation,
|
|
65
|
+
) -> DbEvaluation:
|
|
66
|
+
"""Persist a new evaluation configuration.
|
|
67
|
+
|
|
68
|
+
Raises ValueError if an evaluation with that name already
|
|
69
|
+
exists.
|
|
70
|
+
"""
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
@abstractmethod
|
|
74
|
+
def update(
|
|
75
|
+
self,
|
|
76
|
+
config: DbEvaluation,
|
|
77
|
+
) -> DbEvaluation:
|
|
78
|
+
"""Replace an existing evaluation configuration.
|
|
79
|
+
|
|
80
|
+
The evaluation is identified by ``config.id``.
|
|
81
|
+
|
|
82
|
+
Raises KeyError if the evaluation does not exist.
|
|
83
|
+
"""
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
def get_evaluation(
|
|
87
|
+
self,
|
|
88
|
+
id: str,
|
|
89
|
+
message_collection_repo: MessageCollectionRepository | None = None,
|
|
90
|
+
detector_repo: DetectorRepository | None = None,
|
|
91
|
+
) -> Evaluation:
|
|
92
|
+
"""Return an Evaluation instance for the given id.
|
|
93
|
+
|
|
94
|
+
Depending on the evaluation type, additional repositories
|
|
95
|
+
may be required to resolve referenced objects.
|
|
96
|
+
|
|
97
|
+
Raises KeyError if the evaluation does not exist.
|
|
98
|
+
"""
|
|
99
|
+
from switch_trust.eval.db.base.eval.eval_helpers import ( # noqa: PLC0415 - deferred import cost
|
|
100
|
+
create_evaluation,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return create_evaluation(
|
|
104
|
+
self.get(id),
|
|
105
|
+
message_collection_repo=message_collection_repo,
|
|
106
|
+
detector_repo=detector_repo,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
@abstractmethod
|
|
110
|
+
def delete(self, id: str) -> None:
|
|
111
|
+
"""Delete the evaluation with the given id.
|
|
112
|
+
|
|
113
|
+
Raises KeyError if the evaluation does not exist.
|
|
114
|
+
"""
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
@abstractmethod
|
|
118
|
+
def clear(self) -> None:
|
|
119
|
+
"""Remove all evaluations from the repository."""
|
|
120
|
+
pass
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Standalone function to run a model evaluation end-to-end.
|
|
3
|
+
|
|
4
|
+
Looks up the DbModelEvaluation, creates the core Evaluation and
|
|
5
|
+
Model, creates a DbModelEvaluationRun, and executes the evaluation
|
|
6
|
+
with an observer that persists progress back to the database.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from switch_trust.eval.common.utils import now_utc
|
|
12
|
+
from switch_trust.eval.core.eval.evaluation import Evaluation, EvaluationStatus
|
|
13
|
+
from switch_trust.eval.db.base.detectors.detector_repository import DetectorRepository
|
|
14
|
+
from switch_trust.eval.db.base.eval.eval_repository import EvaluationRepository
|
|
15
|
+
from switch_trust.eval.db.base.eval.model_eval_repository import (
|
|
16
|
+
ModelEvaluationRepository,
|
|
17
|
+
)
|
|
18
|
+
from switch_trust.eval.db.base.eval.model_eval_run_repository import (
|
|
19
|
+
ModelEvaluationRunRepository,
|
|
20
|
+
)
|
|
21
|
+
from switch_trust.eval.db.base.eval.model_eval_run_result_repository import (
|
|
22
|
+
ModelEvaluationRunResultRepository,
|
|
23
|
+
)
|
|
24
|
+
from switch_trust.eval.db.base.eval.model_eval_run_result_types import (
|
|
25
|
+
DbModelEvaluationRunResult,
|
|
26
|
+
)
|
|
27
|
+
from switch_trust.eval.db.base.eval.model_eval_run_types import DbModelEvaluationRun
|
|
28
|
+
from switch_trust.eval.db.base.message.message_collection_repository import (
|
|
29
|
+
MessageCollectionRepository,
|
|
30
|
+
)
|
|
31
|
+
from switch_trust.eval.db.base.models.model_repository import ModelRepository
|
|
32
|
+
|
|
33
|
+
logger = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def run_model_evaluation(
|
|
37
|
+
model_evaluation_id: str,
|
|
38
|
+
concurrency: int,
|
|
39
|
+
model_evaluation_repo: ModelEvaluationRepository,
|
|
40
|
+
evaluation_repo: EvaluationRepository,
|
|
41
|
+
model_repo: ModelRepository,
|
|
42
|
+
run_repo: ModelEvaluationRunRepository,
|
|
43
|
+
message_collection_repo: MessageCollectionRepository | None = None,
|
|
44
|
+
detector_repo: DetectorRepository | None = None,
|
|
45
|
+
result_repo: ModelEvaluationRunResultRepository | None = None,
|
|
46
|
+
run: DbModelEvaluationRun | None = None,
|
|
47
|
+
) -> DbModelEvaluationRun:
|
|
48
|
+
"""Run a model evaluation and persist progress to the database.
|
|
49
|
+
|
|
50
|
+
1. Looks up the DbModelEvaluation by ID
|
|
51
|
+
2. Creates the core Evaluation and Model from their configs
|
|
52
|
+
3. Creates a new DbModelEvaluationRun and persists it
|
|
53
|
+
4. Initialises and runs the evaluation with an observer
|
|
54
|
+
that writes the summary back after each progress update
|
|
55
|
+
5. Returns the completed run
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
model_evaluation_id: ID of the DbModelEvaluation to run.
|
|
59
|
+
concurrency: Max concurrent evaluation tasks.
|
|
60
|
+
model_evaluation_repo: Repository for DbModelEvaluation.
|
|
61
|
+
evaluation_repo: Repository for DbEvaluation.
|
|
62
|
+
model_repo: Repository for DbModel.
|
|
63
|
+
run_repo: Repository for DbModelEvaluationRun.
|
|
64
|
+
message_collection_repo: Required for MESSAGE_COLLECTION
|
|
65
|
+
evaluation types.
|
|
66
|
+
detector_repo: Required for evaluations that use detectors.
|
|
67
|
+
"""
|
|
68
|
+
model_evaluation = model_evaluation_repo.get(
|
|
69
|
+
model_evaluation_id,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
evaluation = evaluation_repo.get_evaluation(
|
|
73
|
+
model_evaluation.evaluation_id,
|
|
74
|
+
message_collection_repo=message_collection_repo,
|
|
75
|
+
detector_repo=detector_repo,
|
|
76
|
+
)
|
|
77
|
+
model = model_repo.get_model(model_evaluation.model_id)
|
|
78
|
+
|
|
79
|
+
if run is None:
|
|
80
|
+
run = DbModelEvaluationRun(
|
|
81
|
+
model_evaluation_id=model_evaluation_id,
|
|
82
|
+
started=now_utc(),
|
|
83
|
+
)
|
|
84
|
+
run_repo.create(run)
|
|
85
|
+
|
|
86
|
+
logger.info(
|
|
87
|
+
"Run %s started for model evaluation %s",
|
|
88
|
+
run.id,
|
|
89
|
+
model_evaluation_id,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def _on_progress(e: Evaluation) -> None:
|
|
93
|
+
summary = e.get_summary()
|
|
94
|
+
run.summary = summary
|
|
95
|
+
if summary.status in (
|
|
96
|
+
EvaluationStatus.FINISHED,
|
|
97
|
+
EvaluationStatus.ERROR,
|
|
98
|
+
):
|
|
99
|
+
run.finished = now_utc()
|
|
100
|
+
run_repo.update(run)
|
|
101
|
+
logger.info(
|
|
102
|
+
"Run %s: %s (%.0f%%)",
|
|
103
|
+
run.id,
|
|
104
|
+
summary.status.value,
|
|
105
|
+
summary.progress * 100,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
evaluation.add_observer(_on_progress)
|
|
109
|
+
try:
|
|
110
|
+
await evaluation.init()
|
|
111
|
+
await evaluation.run(model, concurrency)
|
|
112
|
+
except Exception as e:
|
|
113
|
+
logger.error("Run %s failed: %s", run.id, e)
|
|
114
|
+
finally:
|
|
115
|
+
evaluation.remove_observer(_on_progress)
|
|
116
|
+
|
|
117
|
+
run.summary = evaluation.get_summary()
|
|
118
|
+
run.finished = now_utc()
|
|
119
|
+
run_repo.update(run)
|
|
120
|
+
|
|
121
|
+
if result_repo is not None:
|
|
122
|
+
core_results = evaluation.get_results()
|
|
123
|
+
db_results = [
|
|
124
|
+
DbModelEvaluationRunResult(
|
|
125
|
+
run_id=run.id,
|
|
126
|
+
score=r.score,
|
|
127
|
+
status=r.status,
|
|
128
|
+
error_message=r.error_message,
|
|
129
|
+
session=r.session,
|
|
130
|
+
)
|
|
131
|
+
for r in core_results
|
|
132
|
+
]
|
|
133
|
+
result_repo.create_batch(db_results)
|
|
134
|
+
logger.info(
|
|
135
|
+
"Run %s: stored %d results",
|
|
136
|
+
run.id,
|
|
137
|
+
len(db_results),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
logger.info("Run %s finished", run.id)
|
|
141
|
+
|
|
142
|
+
return run
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
from dataclasses_json import dataclass_json
|
|
8
|
+
|
|
9
|
+
from switch_trust.eval.common.reference import Reference, ReferenceType
|
|
10
|
+
from switch_trust.eval.common.utils import datetime_config, generate_id, now_utc
|
|
11
|
+
from switch_trust.eval.db.base.common_types import SortDirection
|
|
12
|
+
from switch_trust.eval.db.base.eval.model_eval_run_types import DbModelEvaluationRun
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class EvaluationType(str, Enum):
|
|
16
|
+
"""Discriminator for the kind of Evaluation."""
|
|
17
|
+
|
|
18
|
+
MESSAGE_COLLECTION = "message_collection"
|
|
19
|
+
GARAK_PROBE = "garak_probe"
|
|
20
|
+
GARAK_MODULE = "garak_module"
|
|
21
|
+
METRIC_TOXICITY = "metric_toxicity"
|
|
22
|
+
METRIC_CONCISENESS = "metric_conciseness"
|
|
23
|
+
METRIC_FACTUAL_ACCURACY = "metric_factual_accuracy"
|
|
24
|
+
METRIC_INSTRUCTION_ADHERENCE = "metric_instruction_adherence"
|
|
25
|
+
METRIC_TONE = "metric_tone"
|
|
26
|
+
ADVERSARIAL_PROBE = "adversarial_probe"
|
|
27
|
+
TOPIC_GUARD = "topic_guard"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class EvaluationApproach(str, Enum):
|
|
31
|
+
"""Whether an evaluation actively probes the model
|
|
32
|
+
or passively measures a quality metric."""
|
|
33
|
+
|
|
34
|
+
PROBE = "Probe"
|
|
35
|
+
METRIC = "Metric"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass_json
|
|
39
|
+
@dataclass
|
|
40
|
+
class DbEvaluation:
|
|
41
|
+
"""JSON-serialisable description of an Evaluation."""
|
|
42
|
+
|
|
43
|
+
type: EvaluationType
|
|
44
|
+
name: str
|
|
45
|
+
id: str = field(default_factory=generate_id)
|
|
46
|
+
created: datetime = field(
|
|
47
|
+
default_factory=now_utc,
|
|
48
|
+
metadata=datetime_config,
|
|
49
|
+
)
|
|
50
|
+
description: str | None = None
|
|
51
|
+
approach: EvaluationApproach = EvaluationApproach.PROBE
|
|
52
|
+
tags: dict[str, str] = field(default_factory=dict)
|
|
53
|
+
|
|
54
|
+
# -- shared (message_collection, adversarial_probe) --
|
|
55
|
+
message_collection_id: str | None = None
|
|
56
|
+
detector_id: str | None = None
|
|
57
|
+
|
|
58
|
+
# -- garak_probe type --
|
|
59
|
+
probe_name: str | None = None
|
|
60
|
+
|
|
61
|
+
# -- garak_module type --
|
|
62
|
+
module_name: str | None = None
|
|
63
|
+
probe_names: list[str] | None = None
|
|
64
|
+
|
|
65
|
+
# -- adversarial_probe type --
|
|
66
|
+
adversarial_goals: list[str] | None = None
|
|
67
|
+
attack_techniques: list[str] | None = None
|
|
68
|
+
num_prompts: int | None = None
|
|
69
|
+
max_turns: int | None = None
|
|
70
|
+
|
|
71
|
+
# -- topic_guard type --
|
|
72
|
+
agent_objective: str | None = None
|
|
73
|
+
agent_instructions: str | None = None
|
|
74
|
+
|
|
75
|
+
def get_ref(self) -> Reference:
|
|
76
|
+
return Reference(
|
|
77
|
+
self.id,
|
|
78
|
+
self.name,
|
|
79
|
+
ReferenceType.EVALUATION,
|
|
80
|
+
self.description,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class EvaluationSortField(str, Enum):
|
|
85
|
+
NAME = "name"
|
|
86
|
+
CREATED = "created"
|
|
87
|
+
TYPE = "type"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass_json
|
|
91
|
+
@dataclass
|
|
92
|
+
class EvaluationSortOrder:
|
|
93
|
+
field: EvaluationSortField = EvaluationSortField.NAME
|
|
94
|
+
direction: SortDirection = SortDirection.ASC
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass_json
|
|
98
|
+
@dataclass
|
|
99
|
+
class EvaluationListView:
|
|
100
|
+
"""Paginated list of evaluation configurations."""
|
|
101
|
+
|
|
102
|
+
items: list[DbEvaluation] = field(default_factory=list)
|
|
103
|
+
total: int = 0
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass_json
|
|
107
|
+
@dataclass
|
|
108
|
+
class EvaluationDetailModelView:
|
|
109
|
+
"""A model assigned to an evaluation, with last run info."""
|
|
110
|
+
|
|
111
|
+
id: str
|
|
112
|
+
model_ref: Reference
|
|
113
|
+
evaluation_ref: Reference
|
|
114
|
+
created: datetime = field(metadata=datetime_config)
|
|
115
|
+
weight: float = 0.5
|
|
116
|
+
last_run: DbModelEvaluationRun | None = None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass_json
|
|
120
|
+
@dataclass
|
|
121
|
+
class EvaluationDetailView:
|
|
122
|
+
"""An evaluation with its assigned models."""
|
|
123
|
+
|
|
124
|
+
config: DbEvaluation | None = None
|
|
125
|
+
models: list[EvaluationDetailModelView] = field(
|
|
126
|
+
default_factory=list,
|
|
127
|
+
)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Abstract interface for a repository of ModelEvaluations.
|
|
3
|
+
|
|
4
|
+
A ModelEvaluationRepository manages the assignments of
|
|
5
|
+
Evaluations to Models.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
|
|
10
|
+
from switch_trust.eval.db.base.eval.model_eval_types import (
|
|
11
|
+
DbModelEvaluation,
|
|
12
|
+
ModelEvaluationListView,
|
|
13
|
+
ModelEvaluationSortOrder,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ModelEvaluationRepository(ABC):
|
|
18
|
+
"""Repository that manages ModelEvaluation assignments."""
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def list_by_model(
|
|
22
|
+
self,
|
|
23
|
+
model_id: str,
|
|
24
|
+
order: ModelEvaluationSortOrder | None = None,
|
|
25
|
+
offset: int = 0,
|
|
26
|
+
limit: int = 50,
|
|
27
|
+
) -> ModelEvaluationListView:
|
|
28
|
+
"""Return assignments for a given model with pagination.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
model_id: The model to list assignments for.
|
|
32
|
+
order: Sort field and direction.
|
|
33
|
+
offset: Number of items to skip.
|
|
34
|
+
limit: Maximum number of items to return.
|
|
35
|
+
"""
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def get(self, id: str) -> DbModelEvaluation:
|
|
40
|
+
"""Return the assignment with the given id.
|
|
41
|
+
|
|
42
|
+
Raises KeyError if it does not exist.
|
|
43
|
+
"""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def create(
|
|
48
|
+
self,
|
|
49
|
+
config: DbModelEvaluation,
|
|
50
|
+
) -> DbModelEvaluation:
|
|
51
|
+
"""Persist a new model-evaluation assignment.
|
|
52
|
+
|
|
53
|
+
Raises ValueError if an assignment with that name
|
|
54
|
+
already exists.
|
|
55
|
+
"""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
@abstractmethod
|
|
59
|
+
def list_by_evaluation(
|
|
60
|
+
self,
|
|
61
|
+
evaluation_id: str,
|
|
62
|
+
order: ModelEvaluationSortOrder | None = None,
|
|
63
|
+
offset: int = 0,
|
|
64
|
+
limit: int = 50,
|
|
65
|
+
) -> ModelEvaluationListView:
|
|
66
|
+
"""Return assignments for a given evaluation with pagination.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
evaluation_id: The evaluation to list assignments for.
|
|
70
|
+
order: Sort field and direction.
|
|
71
|
+
offset: Number of items to skip.
|
|
72
|
+
limit: Maximum number of items to return.
|
|
73
|
+
"""
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
@abstractmethod
|
|
77
|
+
def clear(self) -> None:
|
|
78
|
+
"""Remove all model-evaluation assignments."""
|
|
79
|
+
pass
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Abstract interface for a repository of ModelEvaluationRuns.
|
|
3
|
+
|
|
4
|
+
A ModelEvaluationRunRepository manages runs of model-evaluation
|
|
5
|
+
assignments, providing create and search operations.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
|
|
10
|
+
from switch_trust.eval.db.base.eval.model_eval_run_types import (
|
|
11
|
+
DbModelEvaluationRun,
|
|
12
|
+
ModelEvaluationRunListView,
|
|
13
|
+
ModelEvaluationRunSortOrder,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ModelEvaluationRunRepository(ABC):
|
|
18
|
+
"""Repository that manages ModelEvaluationRun records."""
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def create(
|
|
22
|
+
self,
|
|
23
|
+
run: DbModelEvaluationRun,
|
|
24
|
+
) -> DbModelEvaluationRun:
|
|
25
|
+
"""Persist a new run."""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def get(self, id: str) -> DbModelEvaluationRun:
|
|
30
|
+
"""Return the run with the given id.
|
|
31
|
+
|
|
32
|
+
Raises KeyError if it does not exist.
|
|
33
|
+
"""
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def update(
|
|
38
|
+
self,
|
|
39
|
+
run: DbModelEvaluationRun,
|
|
40
|
+
) -> DbModelEvaluationRun:
|
|
41
|
+
"""Update the summary and finished timestamp of a run.
|
|
42
|
+
|
|
43
|
+
The run is identified by ``run.id``.
|
|
44
|
+
|
|
45
|
+
Raises KeyError if the run does not exist.
|
|
46
|
+
"""
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def search(
|
|
51
|
+
self,
|
|
52
|
+
model_evaluation_id: str | None = None,
|
|
53
|
+
model_id: str | None = None,
|
|
54
|
+
evaluation_id: str | None = None,
|
|
55
|
+
order: ModelEvaluationRunSortOrder | None = None,
|
|
56
|
+
offset: int = 0,
|
|
57
|
+
limit: int = 50,
|
|
58
|
+
) -> ModelEvaluationRunListView:
|
|
59
|
+
"""Search runs with optional filter and pagination.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
model_evaluation_id: Filter by model-evaluation ID.
|
|
63
|
+
order: Sort field and direction.
|
|
64
|
+
offset: Number of items to skip.
|
|
65
|
+
limit: Maximum number of items to return.
|
|
66
|
+
"""
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
@abstractmethod
|
|
70
|
+
def clear(self) -> None:
|
|
71
|
+
"""Remove all runs."""
|
|
72
|
+
pass
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Abstract interface for a repository of ModelEvaluationRunResults.
|
|
3
|
+
|
|
4
|
+
A ModelEvaluationRunResultRepository manages the leaf-evaluation
|
|
5
|
+
results that belong to a model-evaluation run.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
|
|
10
|
+
from switch_trust.eval.db.base.eval.model_eval_run_result_types import (
|
|
11
|
+
DbModelEvaluationRunResult,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ModelEvaluationRunResultRepository(ABC):
|
|
16
|
+
"""Repository that manages ModelEvaluationRunResult records."""
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def create_batch(
|
|
20
|
+
self,
|
|
21
|
+
results: list[DbModelEvaluationRunResult],
|
|
22
|
+
) -> None:
|
|
23
|
+
"""Persist a batch of results for a run."""
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def get_by_run_id(
|
|
28
|
+
self,
|
|
29
|
+
run_id: str,
|
|
30
|
+
) -> list[DbModelEvaluationRunResult]:
|
|
31
|
+
"""Return all results for a given run."""
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def delete_by_run_id(self, run_id: str) -> None:
|
|
36
|
+
"""Remove all results for a given run."""
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def clear(self) -> None:
|
|
41
|
+
"""Remove all results."""
|
|
42
|
+
pass
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from dataclasses_json import dataclass_json
|
|
4
|
+
|
|
5
|
+
from switch_trust.eval.common.schema import Session
|
|
6
|
+
from switch_trust.eval.common.utils import generate_id
|
|
7
|
+
from switch_trust.eval.core.eval.evaluation import EvaluationStatus
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass_json
|
|
11
|
+
@dataclass
|
|
12
|
+
class DbModelEvaluationRunResult:
|
|
13
|
+
"""A single leaf-evaluation result within a run."""
|
|
14
|
+
|
|
15
|
+
run_id: str
|
|
16
|
+
score: float
|
|
17
|
+
status: EvaluationStatus
|
|
18
|
+
id: str = field(default_factory=generate_id)
|
|
19
|
+
error_message: str | None = None
|
|
20
|
+
tags: dict[str, str] = field(default_factory=dict)
|
|
21
|
+
session: Session | None = None
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
from dataclasses_json import dataclass_json
|
|
6
|
+
|
|
7
|
+
from switch_trust.eval.common.reference import Reference
|
|
8
|
+
from switch_trust.eval.common.utils import datetime_config, generate_id, now_utc
|
|
9
|
+
from switch_trust.eval.core.eval.evaluation import EvaluationSummary
|
|
10
|
+
from switch_trust.eval.db.base.common_types import SortDirection
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass_json
|
|
14
|
+
@dataclass
|
|
15
|
+
class DbModelEvaluationRun:
|
|
16
|
+
"""A single run of a DbModelEvaluation."""
|
|
17
|
+
|
|
18
|
+
model_evaluation_id: str
|
|
19
|
+
id: str = field(default_factory=generate_id)
|
|
20
|
+
created: datetime = field(
|
|
21
|
+
default_factory=now_utc,
|
|
22
|
+
metadata=datetime_config,
|
|
23
|
+
)
|
|
24
|
+
started: datetime | None = field(
|
|
25
|
+
default=None,
|
|
26
|
+
metadata=datetime_config,
|
|
27
|
+
)
|
|
28
|
+
finished: datetime | None = field(
|
|
29
|
+
default=None,
|
|
30
|
+
metadata=datetime_config,
|
|
31
|
+
)
|
|
32
|
+
tags: dict[str, str] = field(default_factory=dict)
|
|
33
|
+
summary: EvaluationSummary | None = None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ModelEvaluationRunSortField(str, Enum):
|
|
37
|
+
CREATED = "created"
|
|
38
|
+
STARTED = "started_at"
|
|
39
|
+
FINISHED = "finished_at"
|
|
40
|
+
SCORE = "score"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass_json
|
|
44
|
+
@dataclass
|
|
45
|
+
class ModelEvaluationRunSortOrder:
|
|
46
|
+
field: ModelEvaluationRunSortField = ModelEvaluationRunSortField.CREATED
|
|
47
|
+
direction: SortDirection = SortDirection.DESC
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass_json
|
|
51
|
+
@dataclass
|
|
52
|
+
class ModelEvaluationRunDetailView:
|
|
53
|
+
"""A model-evaluation run with resolved references."""
|
|
54
|
+
|
|
55
|
+
run: DbModelEvaluationRun
|
|
56
|
+
model_ref: Reference | None = None
|
|
57
|
+
evaluation_ref: Reference | None = None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass_json
|
|
61
|
+
@dataclass
|
|
62
|
+
class ModelEvaluationRunListItem:
|
|
63
|
+
"""A model-evaluation run with resolved references."""
|
|
64
|
+
|
|
65
|
+
run: DbModelEvaluationRun
|
|
66
|
+
model_ref: Reference | None = None
|
|
67
|
+
evaluation_ref: Reference | None = None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass_json
|
|
71
|
+
@dataclass
|
|
72
|
+
class ModelEvaluationRunListView:
|
|
73
|
+
"""Paginated list of model-evaluation runs."""
|
|
74
|
+
|
|
75
|
+
items: list[ModelEvaluationRunListItem] = field(
|
|
76
|
+
default_factory=list,
|
|
77
|
+
)
|
|
78
|
+
total: int = 0
|