5757# Default pyrit_version for database records created before version tracking was added
5858LEGACY_PYRIT_VERSION = "<0.10.0"
5959
60- # Maximum length for string values in ComponentIdentifier.to_dict () when storing to the database.
60+ # Maximum length for string values in ComponentIdentifier.model_dump () when storing to the database.
6161# Longer values are truncated with a "..." suffix.
6262MAX_IDENTIFIER_VALUE_LENGTH : int = 80
6363
@@ -231,16 +231,17 @@ def __init__(self, *, entry: MessagePiece) -> None:
231231 self .prompt_metadata = entry .prompt_metadata
232232 self .targeted_harm_categories = entry .targeted_harm_categories
233233 self .converter_identifiers = [
234- conv .to_dict (max_value_length = MAX_IDENTIFIER_VALUE_LENGTH ) for conv in entry .converter_identifiers
234+ conv .model_dump (context = {"max_value_length" : MAX_IDENTIFIER_VALUE_LENGTH })
235+ for conv in entry .converter_identifiers
235236 ]
236237 # Normalize prompt_target_identifier and convert to dict for JSON serialization
237238 self .prompt_target_identifier = (
238- entry .prompt_target_identifier .to_dict ( max_value_length = MAX_IDENTIFIER_VALUE_LENGTH )
239+ entry .prompt_target_identifier .model_dump ( context = { "max_value_length" : MAX_IDENTIFIER_VALUE_LENGTH } )
239240 if entry .prompt_target_identifier
240241 else {}
241242 )
242243 self .attack_identifier = (
243- entry .attack_identifier .to_dict ( max_value_length = MAX_IDENTIFIER_VALUE_LENGTH )
244+ entry .attack_identifier .model_dump ( context = { "max_value_length" : MAX_IDENTIFIER_VALUE_LENGTH } )
244245 if entry .attack_identifier
245246 else {}
246247 )
@@ -270,21 +271,21 @@ def get_message_piece(self) -> MessagePiece:
270271 stored_version = self .pyrit_version or LEGACY_PYRIT_VERSION
271272 if self .converter_identifiers :
272273 converter_ids = [
273- ComponentIdentifier .from_dict ({** c , "pyrit_version" : stored_version })
274+ ComponentIdentifier .model_validate ({** c , "pyrit_version" : stored_version })
274275 for c in self .converter_identifiers
275276 ]
276277
277278 # Reconstruct ComponentIdentifier with the stored pyrit_version
278279 target_id : ComponentIdentifier | None = None
279280 if self .prompt_target_identifier :
280- target_id = ComponentIdentifier .from_dict (
281+ target_id = ComponentIdentifier .model_validate (
281282 {** self .prompt_target_identifier , "pyrit_version" : stored_version }
282283 )
283284
284285 # Reconstruct ComponentIdentifier with the stored pyrit_version
285286 attack_id : ComponentIdentifier | None = None
286287 if self .attack_identifier :
287- attack_id = ComponentIdentifier .from_dict ({** self .attack_identifier , "pyrit_version" : stored_version })
288+ attack_id = ComponentIdentifier .model_validate ({** self .attack_identifier , "pyrit_version" : stored_version })
288289
289290 message_piece = MessagePiece (
290291 role = self .role ,
@@ -405,8 +406,8 @@ def __init__(self, *, entry: Score) -> None:
405406 normalized_scorer = normalized_scorer .with_eval_hash (
406407 ScorerEvaluationIdentifier (normalized_scorer ).eval_hash
407408 )
408- self .scorer_class_identifier = normalized_scorer .to_dict (
409- max_value_length = MAX_IDENTIFIER_VALUE_LENGTH ,
409+ self .scorer_class_identifier = normalized_scorer .model_dump (
410+ context = { "max_value_length" : MAX_IDENTIFIER_VALUE_LENGTH } ,
410411 )
411412 self .prompt_request_response_id = entry .message_piece_id if entry .message_piece_id else None
412413 self .timestamp = entry .timestamp
@@ -427,7 +428,7 @@ def get_score(self) -> Score:
427428 scorer_identifier = None
428429 stored_version = self .pyrit_version or LEGACY_PYRIT_VERSION
429430 if self .scorer_class_identifier :
430- scorer_identifier = ComponentIdentifier .from_dict (
431+ scorer_identifier = ComponentIdentifier .model_validate (
431432 {** self .scorer_class_identifier , "pyrit_version" : stored_version }
432433 )
433434 return Score (
@@ -779,16 +780,18 @@ def __init__(self, *, entry: AttackResult) -> None:
779780 # Will be removed in 0.15.0.
780781 _attack_strategy_id = entry .get_attack_strategy_identifier ()
781782 self .attack_identifier = (
782- _attack_strategy_id .to_dict (max_value_length = MAX_IDENTIFIER_VALUE_LENGTH ) if _attack_strategy_id else {}
783+ _attack_strategy_id .model_dump (context = {"max_value_length" : MAX_IDENTIFIER_VALUE_LENGTH })
784+ if _attack_strategy_id
785+ else {}
783786 )
784787 # Ensure eval_hash is set before truncation so it survives the DB round-trip
785788 if entry .atomic_attack_identifier and entry .atomic_attack_identifier .eval_hash is None :
786789 entry .atomic_attack_identifier = entry .atomic_attack_identifier .with_eval_hash (
787790 AtomicAttackEvaluationIdentifier (entry .atomic_attack_identifier ).eval_hash
788791 )
789792 self .atomic_attack_identifier = (
790- entry .atomic_attack_identifier .to_dict (
791- max_value_length = MAX_IDENTIFIER_VALUE_LENGTH ,
793+ entry .atomic_attack_identifier .model_dump (
794+ context = { "max_value_length" : MAX_IDENTIFIER_VALUE_LENGTH } ,
792795 )
793796 if entry .atomic_attack_identifier
794797 else None
@@ -911,13 +914,13 @@ def get_attack_result(self) -> AttackResult:
911914 # Reconstruct atomic_attack_identifier, with backward compatibility for
912915 # legacy rows that only have the attack_identifier column.
913916 atomic_id = (
914- ComponentIdentifier .from_dict (self .atomic_attack_identifier ) if self .atomic_attack_identifier else None
917+ ComponentIdentifier .model_validate (self .atomic_attack_identifier ) if self .atomic_attack_identifier else None
915918 )
916919 if atomic_id is None and self .attack_identifier :
917920 from pyrit .models import build_atomic_attack_identifier
918921
919922 atomic_id = build_atomic_attack_identifier (
920- attack_identifier = ComponentIdentifier .from_dict (self .attack_identifier ),
923+ attack_identifier = ComponentIdentifier .model_validate (self .attack_identifier ),
921924 )
922925
923926 # Deserialize retry events from JSON
@@ -1037,8 +1040,8 @@ def __init__(self, *, entry: ScenarioResult) -> None:
10371040 self .scenario_init_data = entry .scenario_identifier .init_data
10381041 # Convert ComponentIdentifier to dict for JSON storage
10391042 self .objective_target_identifier = (
1040- entry .objective_target_identifier .to_dict (
1041- max_value_length = MAX_IDENTIFIER_VALUE_LENGTH ,
1043+ entry .objective_target_identifier .model_dump (
1044+ context = { "max_value_length" : MAX_IDENTIFIER_VALUE_LENGTH } ,
10421045 )
10431046 if entry .objective_target_identifier
10441047 else None
@@ -1050,8 +1053,8 @@ def __init__(self, *, entry: ScenarioResult) -> None:
10501053 )
10511054
10521055 self .objective_scorer_identifier = (
1053- entry .objective_scorer_identifier .to_dict (
1054- max_value_length = MAX_IDENTIFIER_VALUE_LENGTH ,
1056+ entry .objective_scorer_identifier .model_dump (
1057+ context = { "max_value_length" : MAX_IDENTIFIER_VALUE_LENGTH } ,
10551058 )
10561059 if entry .objective_scorer_identifier
10571060 else None
@@ -1104,12 +1107,12 @@ def get_scenario_result(self) -> ScenarioResult:
11041107 # Convert dict back to ComponentIdentifier with the stored pyrit_version
11051108 scorer_identifier = None
11061109 if self .objective_scorer_identifier :
1107- scorer_identifier = ComponentIdentifier .from_dict (
1110+ scorer_identifier = ComponentIdentifier .model_validate (
11081111 {** self .objective_scorer_identifier , "pyrit_version" : stored_version }
11091112 )
11101113
11111114 # Convert dict back to ComponentIdentifier for reconstruction
1112- target_identifier = ComponentIdentifier .from_dict (self .objective_target_identifier )
1115+ target_identifier = ComponentIdentifier .model_validate (self .objective_target_identifier )
11131116
11141117 # Deserialize display_group_map if stored
11151118 display_group_map : dict [str , str ] | None = None
0 commit comments