33
44from __future__ import annotations
55
6+ import warnings
67from dataclasses import dataclass , field
7- from typing import Literal , Optional , get_args
8+ from typing import Literal , get_args
89
10+ from pyrit .common .deprecation import print_deprecation_message
911from pyrit .message_normalizer import (
1012 ConversationContextNormalizer ,
1113 MessageStringNormalizer ,
@@ -34,16 +36,25 @@ class PrependedConversationConfig:
3436 # Must implement MessageStringNormalizer (e.g., TokenizerTemplateNormalizer or ConversationContextNormalizer).
3537 # When None and normalization is needed (e.g., for non-chat targets), a default
3638 # ConversationContextNormalizer is used that produces "Turn N: User/Assistant" format.
37- message_normalizer : Optional [MessageStringNormalizer ] = None
38-
39- # Behavior when the target is a PromptTarget but not a chat-capable PromptTarget:
40- # - "normalize_first_turn": Normalize the prepended conversation into a string and
41- # store it in ConversationState.normalized_prepended_context. This context will be
42- # prepended to the first message sent to the target. Uses objective_target_context_normalizer
43- # if provided, otherwise falls back to ConversationContextNormalizer.
44- # - "raise": Raise a ValueError. Use this when prepended conversation history must be
45- # maintained by the target (i.e., target must be a chat-capable PromptTarget).
46- non_chat_target_behavior : Literal ["normalize_first_turn" , "raise" ] = "normalize_first_turn"
39+ message_normalizer : MessageStringNormalizer | None = None
40+
41+ # Deprecated: this option will be removed in v0.16.0. Setting this field to any
42+ # non-None value emits a DeprecationWarning. In this release, ``"raise"`` still
43+ # raises ValueError on non-chat targets; ``"normalize_first_turn"`` and ``None``
44+ # both normalize the prepended conversation into the first turn (via
45+ # ``message_normalizer``; default: ConversationContextNormalizer). In v0.16.0
46+ # non-chat targets will always normalize; there is no replacement for the
47+ # ``"raise"`` behavior.
48+ non_chat_target_behavior : Literal ["normalize_first_turn" , "raise" ] | None = None
49+
50+ def __post_init__ (self ) -> None :
51+ """Emit a DeprecationWarning when the deprecated ``non_chat_target_behavior`` field is set."""
52+ if self .non_chat_target_behavior is not None :
53+ print_deprecation_message (
54+ old_item = "PrependedConversationConfig(non_chat_target_behavior=...)" ,
55+ new_item = "PrependedConversationConfig() (non-chat targets always normalize the prepended conversation)" ,
56+ removed_in = "0.16.0" ,
57+ )
4758
4859 def get_message_normalizer (self ) -> MessageStringNormalizer :
4960 """
@@ -58,30 +69,44 @@ def get_message_normalizer(self) -> MessageStringNormalizer:
5869 @classmethod
5970 def default (cls ) -> PrependedConversationConfig :
6071 """
61- Create a default configuration with converters applied to all roles.
72+ Return a deprecated configuration with ``non_chat_target_behavior="raise"``.
73+
74+ .. deprecated::
75+ ``default()`` is deprecated and will be removed in v0.16.0. Use
76+ ``PrependedConversationConfig()`` instead. In this release the returned
77+ configuration still raises on non-chat targets; in v0.16.0 the ``"raise"``
78+ branch is removed and non-chat targets will always normalize the prepended
79+ conversation into the first turn.
6280
6381 Returns:
64- A configuration that applies converters to all prepended messages,
65- raising an error for non-chat targets.
82+ A configuration equivalent to ``PrependedConversationConfig(non_chat_target_behavior="raise")``.
6683 """
67- return cls (
68- apply_converters_to_roles = list ( get_args ( ChatMessageRole )) ,
69- message_normalizer = None ,
70- non_chat_target_behavior = "raise " ,
84+ print_deprecation_message (
85+ old_item = "PrependedConversationConfig.default()" ,
86+ new_item = "PrependedConversationConfig() (non-chat targets always normalize the prepended conversation)" ,
87+ removed_in = "0.16.0 " ,
7188 )
89+ # Suppress the __post_init__ deprecation warning so callers see exactly
90+ # one warning (the one for default()) rather than two for a single deprecated call.
91+ with warnings .catch_warnings ():
92+ warnings .simplefilter ("ignore" , DeprecationWarning )
93+ return cls (non_chat_target_behavior = "raise" )
7294
7395 @classmethod
7496 def for_non_chat_target (
7597 cls ,
7698 * ,
77- message_normalizer : Optional [ MessageStringNormalizer ] = None ,
78- apply_converters_to_roles : Optional [ list [ChatMessageRole ]] = None ,
99+ message_normalizer : MessageStringNormalizer | None = None ,
100+ apply_converters_to_roles : list [ChatMessageRole ] | None = None ,
79101 ) -> PrependedConversationConfig :
80102 """
81103 Create a configuration for use with non-chat targets.
82104
83- This configuration normalizes the prepended conversation into a text block
84- that will be prepended to the first message sent to the target.
105+ .. deprecated::
106+ ``for_non_chat_target()`` is deprecated and will be removed in v0.16.0.
107+ Non-chat targets always normalize the prepended conversation into the
108+ first turn, so this factory is equivalent to ``PrependedConversationConfig(...)``
109+ with the same arguments. Use the default constructor instead.
85110
86111 Args:
87112 message_normalizer: Normalizer for formatting the prepended conversation into a string.
@@ -92,10 +117,21 @@ def for_non_chat_target(
92117 Returns:
93118 A configuration that normalizes the prepended conversation for non-chat targets.
94119 """
95- return cls (
96- apply_converters_to_roles = (
97- apply_converters_to_roles if apply_converters_to_roles is not None else list (get_args (ChatMessageRole ))
98- ),
99- message_normalizer = message_normalizer ,
100- non_chat_target_behavior = "normalize_first_turn" ,
120+ print_deprecation_message (
121+ old_item = "PrependedConversationConfig.for_non_chat_target()" ,
122+ new_item = "PrependedConversationConfig() (non-chat targets always normalize the prepended conversation)" ,
123+ removed_in = "0.16.0" ,
101124 )
125+ # Suppress the __post_init__ deprecation warning so callers see exactly one
126+ # warning (the one for for_non_chat_target()) rather than two.
127+ with warnings .catch_warnings ():
128+ warnings .simplefilter ("ignore" , DeprecationWarning )
129+ return cls (
130+ apply_converters_to_roles = (
131+ apply_converters_to_roles
132+ if apply_converters_to_roles is not None
133+ else list (get_args (ChatMessageRole ))
134+ ),
135+ message_normalizer = message_normalizer ,
136+ non_chat_target_behavior = "normalize_first_turn" ,
137+ )
0 commit comments