Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate string output/input to Turn objects #1089

Open
wants to merge 92 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
fa193b0
start moving to abstracted prompt objects
leondz Jan 20, 2025
f6587fe
renaming Prompt -> Turn (incomplete)
leondz Jan 27, 2025
e4edeb6
attempt turns are now instances of Turn
leondz Jan 27, 2025
9f86eca
file reading helper
leondz Jan 27, 2025
e0aa817
use Turn() in turns
leondz Jan 27, 2025
c4a0e00
specify dict-based serialisation
leondz Jan 27, 2025
31f5393
support string use insetting attempt values
leondz Jan 27, 2025
08fd05f
base detectors operate on turn text
leondz Jan 27, 2025
ae77d0f
stringdetector only operates on output.text
leondz Jan 27, 2025
d4ecf95
stringdetector only operates on output.text
leondz Jan 27, 2025
6f429cf
serialise turns in eval logging
leondz Jan 27, 2025
895eaa4
migrate base buff tests, buffs.lowercase
leondz Jan 27, 2025
84a9754
migrate encoding buff
leondz Jan 27, 2025
e0fda46
migrate encoding buff
leondz Jan 27, 2025
25b8172
migrate leakreplay, detector test case
leondz Jan 27, 2025
887c18d
Turns can have text==None but cannot be Nones themselves
leondz Jan 27, 2025
5c4cc11
migrate detectors: continuation, fileformats, divergence, encoding, n…
leondz Jan 27, 2025
d519ff1
migrate many detectors
leondz Jan 27, 2025
3b65324
migrate HFDetectors
leondz Jan 27, 2025
512780d
migrate llmaj detector
leondz Jan 27, 2025
57ad823
migrate base detector tests
leondz Jan 27, 2025
1e1f147
migrate fileformats detectors and tests
leondz Jan 27, 2025
3db4bc4
migrate lrl buff
leondz Jan 27, 2025
47d912f
get None responsibility in the right place (turn content - can't repl…
leondz Jan 27, 2025
6147759
clarify fileformat typing wrt. Turn
leondz Jan 27, 2025
8fa359c
migrate function_single test
leondz Jan 27, 2025
0370260
Merge branch 'NVIDIA:main' into feature/turn_objects
leondz Jan 27, 2025
1c455d1
migrate base generator and base generator tests
leondz Jan 28, 2025
6a6ad47
test generators migrated
leondz Jan 28, 2025
d7b2e71
black
leondz Jan 28, 2025
4c11faf
migrate test, function generators to Turn
leondz Jan 28, 2025
8087442
migrate rest generator
leondz Jan 28, 2025
23dc5eb
migrate replicate generator
leondz Jan 28, 2025
3b257a9
migrate ollama generator
leondz Jan 28, 2025
8b0c557
migrate octo generator
leondz Jan 28, 2025
8152951
migrate nvcf generator
leondz Jan 28, 2025
98486b3
migrate nemo generator
leondz Jan 28, 2025
e5f6513
migrate langchain serve generator
leondz Jan 28, 2025
3aab2f4
migrate ggml generator
leondz Jan 28, 2025
0005245
migrate groq generator
leondz Jan 28, 2025
7c350da
migrate guardrails generator
leondz Jan 28, 2025
0ae2b81
migration on hf, litellm, octo, ollama
leondz Jan 29, 2025
6a3d66a
merge main
leondz Feb 13, 2025
ab9e01c
prune ConversationalPipeline
leondz Feb 13, 2025
5d7b697
update hf to using Turn
leondz Feb 13, 2025
98e50db
add Turn typechecking in base generator .generate() to help everyone …
leondz Feb 13, 2025
41aa3a0
update nvcf, octo, rest with Turn
leondz Feb 13, 2025
7c7b853
consider new pattern for turn extra components
leondz Feb 13, 2025
10ae255
add Turn to generator tests
leondz Feb 14, 2025
e897b8a
i am altering the Turn object. pray i do not alter it any further (pr…
leondz Feb 14, 2025
fef9632
update atkgen to take s instead of its local
leondz Feb 14, 2025
814bc92
map detectors.judge over to Turn
leondz Feb 14, 2025
9bcbc06
update openai to expect turn for single interactions
leondz Feb 14, 2025
41484bc
update xss rx constant name
leondz Feb 14, 2025
51b6e6c
catch a string return
leondz Feb 14, 2025
2130384
cast expected test results to Turn
leondz Feb 14, 2025
f4a644b
update Turn.__str__ to expect 1 part in text-only case
leondz Feb 14, 2025
49a9b17
move openai json to valid json
leondz Feb 17, 2025
957c1ec
Turn inherits from dict for serialisation
leondz Feb 17, 2025
c154a5c
migrate openaicompatible, and type-check its output
leondz Feb 17, 2025
c5691ce
move hf, watson json test files to valid json
leondz Feb 17, 2025
24a6852
migrate watson to Turn
leondz Feb 17, 2025
a69bf8c
migrate litellm
leondz Feb 17, 2025
6c54bed
migrate OllamaGeneratorChat to Turn
leondz Feb 17, 2025
6ee1d92
set expectations about Turn structure and serialisability
leondz Feb 17, 2025
38448e3
clarify docs on default turn part names; migrate nim.Vision; add imag…
leondz Feb 17, 2025
e8f988d
migrate llava
leondz Feb 17, 2025
4d75baa
add test vision generator
leondz Feb 17, 2025
e3a966b
probes.base.Probe.prompts init to empty list
leondz Feb 17, 2025
5b60ed7
move visual jailbreak load up into init, do inheritance correctly
leondz Feb 17, 2025
38324a5
change repr a bit
leondz Feb 17, 2025
1372191
refactor visual jailbreak, add tests
leondz Feb 17, 2025
3610cf6
migrate langchain, cohere
leondz Feb 17, 2025
dba5a20
Merge branch 'NVIDIA:main' into feature/turn_objects
leondz Feb 17, 2025
6316d27
migrate openai to Turn; add typechecking flag to bypass Turn check (u…
leondz Feb 17, 2025
9a30123
update to handle ollama.list() output type
leondz Feb 17, 2025
6d85cf6
migrate ollama & tests to Turn
leondz Feb 17, 2025
911c16a
give the 'not found' exception if the error's a not found one, but ca…
leondz Feb 17, 2025
af4b409
migrate groq to Turn
leondz Feb 17, 2025
3ea5834
adjust OpenAI o- message scope
leondz Feb 17, 2025
ff1331d
don't have opinions about init'ing probes base prompts
leondz Feb 17, 2025
1e84ad9
update exception pattern thrown when invalid openai litellm model req…
leondz Feb 18, 2025
e49e49f
type check generators for Turn patterns
leondz Feb 18, 2025
3ec028b
brief refactor in detector checking
leondz Feb 18, 2025
e86cf32
header docs for Turn
leondz Feb 18, 2025
3569f39
rm conversational pipeline cache entry
leondz Feb 19, 2025
2779129
pretty print test json data to reduce churn
leondz Feb 19, 2025
061dbcc
merge in skip seq feature
leondz Feb 21, 2025
393a22e
restore Turn-based tests for base generators
leondz Feb 21, 2025
45609b2
refactor generator tests, leaving placeholder for base
leondz Feb 21, 2025
916e962
type annotations
leondz Feb 26, 2025
57c13b8
Merge branch 'NVIDIA:main' into feature/turn_objects
leondz Mar 4, 2025
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
Prev Previous commit
Next Next commit
migrate base generator and base generator tests
  • Loading branch information
leondz committed Jan 28, 2025
commit 1c455d16dbee13a5737fe5eaae683273621d0284
15 changes: 8 additions & 7 deletions garak/generators/base.py
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
import tqdm

from garak import _config
from garak.attempt import Turn
from garak.configurable import Configurable
import garak.resources.theme

@@ -58,8 +59,8 @@ def __init__(self, name="", config_root=_config):
logging.info("generator init: %s", self)

def _call_model(
self, prompt: str, generations_this_call: int = 1
) -> List[Union[str, None]]:
self, prompt: Turn, generations_this_call: int = 1
) -> List[Union[Turn, None]]:
"""Takes a prompt and returns an API output

_call_api() is fully responsible for the request, and should either
@@ -73,21 +74,21 @@ def _pre_generate_hook(self):
pass

@staticmethod
def _verify_model_result(result: List[Union[str, None]]):
def _verify_model_result(result: List[Union[Turn, None]]):
assert isinstance(result, list), "_call_model must return a list"
assert (
len(result) == 1
), f"_call_model must return a list of one item when invoked as _call_model(prompt, 1), got {result}"
assert (
isinstance(result[0], str) or result[0] is None
), "_call_model's item must be a string or None"
isinstance(result[0], Turn) or result[0] is None
), "_call_model's item must be a Turn or None"

def clear_history(self):
pass

def generate(
self, prompt: str, generations_this_call: int = 1
) -> List[Union[str, None]]:
self, prompt: Turn, generations_this_call: int = 1
) -> List[Union[Turn, None]]:
"""Manages the process of getting generations out from a prompt

This will involve iterating through prompts, getting the generations
83 changes: 42 additions & 41 deletions tests/generators/test_generators.py
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@

from garak import _plugins
from garak import _config
from garak.attempt import Turn
from garak.generators.test import Blank, Repeat, Single
from garak.generators.base import Generator

@@ -22,51 +23,51 @@

def test_generators_test_blank():
g = Blank(DEFAULT_GENERATOR_NAME)
output = g.generate(prompt="test", generations_this_call=5)
output = g.generate(prompt=Turn("test"), generations_this_call=5)
assert output == [
"",
"",
"",
"",
"",
], "generators.test.Blank with generations_this_call=5 should return five empty strings"
Turn(""),
Turn(""),
Turn(""),
Turn(""),
Turn(""),
], "generators.test.Blank with generations_this_call=5 should return five Turns with empty text"


def test_generators_test_repeat():
g = Repeat(DEFAULT_GENERATOR_NAME)
output = g.generate(prompt=DEFAULT_PROMPT_TEXT)
output = g.generate(prompt=Turn(DEFAULT_PROMPT_TEXT))
assert output == [
DEFAULT_PROMPT_TEXT
], "generators.test.Repeat should send back a list of the posed prompt string"
Turn(DEFAULT_PROMPT_TEXT)
], "generators.test.Repeat should send back a list of the posed prompt Turn"


def test_generators_test_single_one():
g = Single(DEFAULT_GENERATOR_NAME)
output = g.generate(prompt="test")
output = g.generate(prompt=Turn("test"))
assert isinstance(
output, list
), "Single generator .generate() should send back a list"
assert (
len(output) == 1
), "Single.generate() without generations_this_call should send a list of one string"
), "Single.generate() without generations_this_call should send a list of length one"
assert isinstance(
output[0], str
), "Single generator output list should contain strings"
output[0], Turn
), "Single generator output list should contain Turns"

output = g._call_model(prompt="test")
output = g._call_model(prompt=Turn("test"))
assert isinstance(output, list), "Single generator _call_model should return a list"
assert (
len(output) == 1
), "_call_model w/ generations_this_call 1 should return a list of length 1"
assert isinstance(
output[0], str
), "Single generator output list should contain strings"
output[0], Turn
), "Single generator output list should contain Turns"


def test_generators_test_single_many():
random_generations = random.randint(2, 12)
g = Single(DEFAULT_GENERATOR_NAME)
output = g.generate(prompt="test", generations_this_call=random_generations)
output = g.generate(prompt=Turn("test"), generations_this_call=random_generations)
assert isinstance(
output, list
), "Single generator .generate() should send back a list"
@@ -75,67 +76,67 @@ def test_generators_test_single_many():
), "Single.generate() with generations_this_call should return equal generations"
for i in range(0, random_generations):
assert isinstance(
output[i], str
), "Single generator output list should contain strings (all positions)"
output[i], Turn
), "Single generator output list should contain Turns (all positions)"


def test_generators_test_single_too_many():
g = Single(DEFAULT_GENERATOR_NAME)
with pytest.raises(ValueError):
output = g._call_model(prompt="test", generations_this_call=2)
output = g._call_model(prompt=Turn("test"), generations_this_call=2)
assert "Single._call_model should refuse to process generations_this_call > 1"


def test_generators_test_blank_one():
g = Blank(DEFAULT_GENERATOR_NAME)
output = g.generate(prompt="test")
output = g.generate(prompt=Turn("test"))
assert isinstance(
output, list
), "Blank generator .generate() should send back a list"
assert (
len(output) == 1
), "Blank generator .generate() without generations_this_call should return a list of length 1"
assert isinstance(
output[0], str
), "Blank generator output list should contain strings"
assert (
output[0] == ""
), "Blank generator .generate() output list should contain strings"
output[0], Turn
), "Blank generator output list should contain Turns"
assert output[0] == Turn(
""
), "Blank generator .generate() output list should contain Turns"


def test_generators_test_blank_many():
g = Blank(DEFAULT_GENERATOR_NAME)
output = g.generate(prompt="test", generations_this_call=2)
output = g.generate(prompt=Turn("test"), generations_this_call=2)
assert isinstance(
output, list
), "Blank generator .generate() should send back a list"
assert (
len(output) == 2
), "Blank generator .generate() w/ generations_this_call=2 should return a list of length 2"
assert isinstance(
output[0], str
), "Blank generator output list should contain strings (first position)"
output[0], Turn
), "Blank generator output list should contain Turnd (first position)"
assert isinstance(
output[1], str
), "Blank generator output list should contain strings (second position)"
assert (
output[0] == ""
), "Blank generator .generate() output list should contain strings (first position)"
assert (
output[1] == ""
), "Blank generator .generate() output list should contain strings (second position)"
output[1], Turn
), "Blank generator output list should contain Turns (second position)"
assert output[0] == Turn(
""
), "Blank generator .generate() output list should contain Turns (first position)"
assert output[1] == Turn(
""
), "Blank generator .generate() output list should contain Turns (second position)"


def test_parallel_requests():
_config.system.parallel_requests = 2

g = _plugins.load_plugin("generators.test.Lipsum")
result = g.generate(prompt="this is a test", generations_this_call=3)
result = g.generate(prompt=Turn("this is a test"), generations_this_call=3)
assert isinstance(result, list), "Generator generate() should return a list"
assert len(result) == 3, "Generator should return 3 results as requested"
assert all(
isinstance(item, str) for item in result
), "All items in the generate result should be strings"
isinstance(item, Turn) for item in result
), "All items in the generate result should be Turns"
assert all(
len(item) > 0 for item in result
), "All generated strings should be non-empty"