Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pyrit/models/seeds/seed_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import logging
import uuid
from collections import defaultdict
from copy import deepcopy
from typing import TYPE_CHECKING, Annotated, Any

from pydantic import BaseModel, ConfigDict, Field, model_validator
Expand Down Expand Up @@ -460,7 +461,7 @@ def _prompts_to_messages(self, prompts: Sequence[SeedPrompt], *, is_history: boo
original_value_data_type=prompt.data_type or "text",
conversation_id=str(prompt.prompt_group_id),
sequence=sequence,
prompt_metadata=prompt.metadata or {},
prompt_metadata=deepcopy(prompt.metadata) if prompt.metadata else {},
)
if is_history or piece.api_role in {"assistant", "tool"}:
piece.set_simulated_role()
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/models/test_seed_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,29 @@ def test_seed_prompts_without_metadata_convert_to_messages() -> None:
assert [message.get_piece().prompt_metadata for message in group.user_messages] == [{}, {}]


def test_derived_message_metadata_is_independent_of_seed_metadata() -> None:
"""Mutating a derived message's nested metadata must not change the source seed."""
group = SeedGroup(
seeds=[
SeedPrompt(value="Earlier request", role="user", sequence=0, metadata={"nested": {"labels": ["initial"]}}),
SeedPrompt(value="Next request", role="user", sequence=1, metadata={"nested": {"labels": ["next"]}}),
]
)

history = group.prepended_conversation
assert history is not None
history[0].get_piece().prompt_metadata["nested"]["labels"].append("history")
next_message = group.next_message
assert next_message is not None
next_message.get_piece().prompt_metadata["nested"]["labels"].append("next-turn")

assert group.seeds[0].metadata == {"nested": {"labels": ["initial"]}}
assert group.seeds[1].metadata == {"nested": {"labels": ["next"]}}
later_history = group.prepended_conversation
assert later_history is not None
assert later_history[0].get_piece().prompt_metadata["nested"] == {"labels": ["initial"]}


class TestSeedGroupInit:
"""Tests for SeedGroup initialization."""

Expand Down