FEAT: Add remove_seeds_from_memory_async to memory#2243
Open
blahdeblahde wants to merge 1 commit into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds first-class support for deleting seed prompts from PyRIT memory by introducing remove_seeds_from_memory_async, mirroring the existing get_seeds filter surface so users no longer need backend-specific SQL for seed cleanup.
Changes:
- Extracts seed filter construction into a shared private helper (
_build_seed_filter_conditions) used by both seed querying and deletion. - Adds
remove_seeds_from_memory_asyncto delete matchingSeedEntryrows transactionally and return the number removed (with a no-filter safety guard). - Adds unit tests and documentation demonstrating a “preview via
get_seeds, then delete viaremove_seeds_from_memory_async” workflow.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 13 comments.
| File | Description |
|---|---|
pyrit/memory/memory_interface.py |
Adds shared seed-filter builder and new async seed removal API implemented via SQLAlchemy. |
tests/unit/memory/memory_interface/test_interface_remove_seeds.py |
Adds unit coverage for common filter cases and safety behavior. |
doc/code/memory/8_seed_database.py |
Documents seed removal usage and recommended preview-then-delete workflow. |
doc/code/memory/8_seed_database.ipynb |
Syncs the same documentation updates into the notebook format. |
Comment on lines
+10
to
+11
| @pytest.mark.asyncio | ||
| async def test_remove_seeds_by_dataset_name(sqlite_instance: MemoryInterface): |
Comment on lines
+26
to
+27
| @pytest.mark.asyncio | ||
| async def test_remove_seeds_by_dataset_name_pattern(sqlite_instance: MemoryInterface): |
Comment on lines
+43
to
+44
| @pytest.mark.asyncio | ||
| async def test_remove_seeds_by_added_by(sqlite_instance: MemoryInterface): |
Comment on lines
+59
to
+60
| @pytest.mark.asyncio | ||
| async def test_remove_seeds_multi_filter_narrowing(sqlite_instance: MemoryInterface): |
Comment on lines
+75
to
+76
| @pytest.mark.asyncio | ||
| async def test_remove_seeds_no_filter_raises_value_error(sqlite_instance: MemoryInterface): |
| remove_seeds_from_memory_async stay in sync and cannot drift. | ||
|
|
||
| Args: | ||
| value (str): The value to match by substring. If None, all values are returned. |
|
|
||
| Args: | ||
| value (str): The value to match by substring. If None, all values are returned. | ||
| value_sha256 (str): The SHA256 hash of the value to match. If None, all values are returned. |
| prompt_group_ids (Sequence[uuid.UUID]): A list of prompt group IDs to filter by. | ||
|
|
||
| Returns: | ||
| Sequence[SeedPrompt]: A list of prompts matching the criteria. |
|
|
||
| Args: | ||
| value (str): The value to match by substring. If None, all values are considered. | ||
| value_sha256 (str): The SHA256 hash of the value to match. If None, all values are considered. |
Comment on lines
+2327
to
+2329
| query = session.query(SeedEntry).filter(and_(*conditions)) | ||
| count = query.delete(synchronize_session="fetch") | ||
| session.commit() |
Adds an API to remove seed prompts from memory using the same filter parameters as get_seeds (dataset_name, dataset_name_pattern, added_by, harm_categories, authors, groups, source, value_sha256, etc.). Implementation: - Extract filter-building logic from get_seeds into shared _build_seed_filter_conditions helper to prevent drift - Add remove_seeds_from_memory_async that uses the shared helper - Require at least one filter (raises ValueError if none provided) - Single transaction with rollback on failure - Works across DuckDB, SQLite, Azure SQL (uses SQLAlchemy ORM) Unit tests cover: exact name filter, LIKE pattern, multi-filter narrowing, no-filter ValueError, zero-match return, harm_categories, and source filter. Docs: add a 'Removing Seeds from the Database' section to the seed database notebook (8_seed_database.py/.ipynb) demonstrating the preview-then-remove workflow. Resolves AB#5688 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f9e3cc10-5c77-4384-92d9-d27dad9baea2
blahdeblahde
force-pushed
the
blahdeblahde-remove-seeds-from-memory-api
branch
from
July 21, 2026 22:38
2d45b57 to
0e3ae02
Compare
Contributor
Author
|
Thanks for the review! Addressed all points in the latest push:
|
Comment on lines
+2328
to
+2338
| # Delete matching rows in a single transaction so it is atomic across backends. | ||
| with closing(self.get_session()) as session: | ||
| try: | ||
| query = session.query(SeedEntry).filter(and_(*conditions)) | ||
| count = query.delete(synchronize_session=False) | ||
| session.commit() | ||
| return count | ||
| except SQLAlchemyError as e: | ||
| session.rollback() | ||
| logger.exception(f"Failed to remove seeds from memory: {e}") | ||
| raise |
Contributor
Author
|
@microsoft-github-policy-service agree company="Microsoft" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
PyRIT memory can add seed prompt datasets (via
add_seed_datasets_to_memory_async/add_seeds_to_memory_async) and query them withget_seeds, but there is no counterpart for removing seeds. Today users have to drop into raw SQL, which is error-prone and differs across the supported backends (DuckDB, SQLite, Azure SQL).This PR adds
remove_seeds_from_memory_async, which accepts the same filter parameters asget_seeds(dataset_name,dataset_name_pattern,added_by,harm_categories,authors,groups,source,value_sha256,data_types,seed_type,parameters,metadata,prompt_group_ids) and returns the number of seeds removed.Recommended workflow — preview, then delete with the same filters:
Implementation
get_seedsinto a shared private helper (_build_seed_filter_conditions) so both query and removal build conditions from a single source and cannot drift.remove_seeds_from_memory_asyncdeletes matching rows in a single transaction using the SQLAlchemy ORM (rollback on error), so it behaves consistently across DuckDB, SQLite, and Azure SQL.Safety
ValueErrorto prevent accidentally wiping the entire seed database.Tests and Documentation
Tests —
tests/unit/memory/memory_interface/test_interface_remove_seeds.pycovers:dataset_namematchdataset_name_pattern(SQLLIKE)dataset_name+added_by)ValueError0and deletes nothingharm_categories(list field) andsourcefiltersDocumentation — added a "Removing Seeds from the Database" section to
doc/code/memory/8_seed_database.py(and the synced.ipynb) demonstrating the preview-then-remove workflow.