feat(Integrated Garak):

This commit is contained in:
Alexander Myasoedov
2024-04-27 21:44:38 +03:00
parent fa209684d9
commit 74461efaa0
10 changed files with 161 additions and 37 deletions
+9
View File
@@ -127,6 +127,15 @@ REGISTRY = [
"selected": False,
"url": "https://github.com/tml-epfl/llm-adaptive-attacks",
},
{
"dataset_name": "Garak",
"num_prompts": 0,
"tokens": 0,
"approx_cost": 0.0,
"source": "Github: https://github.com/leondz/garak",
"selected": False,
"url": "https://github.com/leondz/garak",
},
{
"dataset_name": "Custom CSV",
"num_prompts": len(load_local_csv().prompts),
+17 -25
View File
@@ -7,7 +7,7 @@ import pandas as pd
from loguru import logger
from agentic_security.probe_data import stenography_fn
from agentic_security.probe_data.modules import adaptive_attacks
from agentic_security.probe_data.modules import adaptive_attacks, garak_tool
IS_VERCEL = os.getenv("IS_VERCEL", "f") == "t"
@@ -32,6 +32,7 @@ class ProbeDataset:
prompts: list[str]
tokens: int
approx_cost: float
lazy: bool = False
def metadata_summary(self):
return {
@@ -168,10 +169,7 @@ def load_dataset_v5():
)
def prepare_prompts(
dataset_names,
budget,
):
def prepare_prompts(dataset_names, budget, tools_inbox=None):
# ## Datasets used and cleaned:
# markush1/LLM-Jailbreak-Classifier
# 1. Open-Orca/OpenOrca
@@ -203,6 +201,11 @@ def prepare_prompts(
"llm-adaptive-attacks": lambda: dataset_from_iterator(
"llm-adaptive-attacks", adaptive_attacks.Module(group).apply()
),
"Garak": lambda: dataset_from_iterator(
"Garak",
garak_tool.Module(group, tools_inbox=tools_inbox).apply(),
lazy=True,
),
"GPT fuzzer": lambda: [],
}
@@ -217,22 +220,6 @@ def prepare_prompts(
return group + dynamic_groups
class MutationFn:
def __init__(self, mutation_fn):
self.mutation_fn = mutation_fn
self.mutation_fn_name = mutation_fn.__name__
self.input = ""
self.output = ""
def __call__(self, prompt):
self.input = prompt
self.output = self.mutation_fn(prompt)
return self.output
def __str__(self):
return f"{self.mutation_fn_name}({self.input}) => {self.output}"
class Stenography:
fn_library = {
"rot5": stenography_fn.rot5,
@@ -295,7 +282,7 @@ def load_local_csv() -> ProbeDataset:
)
def dataset_from_iterator(name: str, iterator) -> list:
def dataset_from_iterator(name: str, iterator, lazy=False) -> list:
"""Convert an iterator into a list of prompts and create a ProbeDataset
object.
@@ -306,9 +293,14 @@ def dataset_from_iterator(name: str, iterator) -> list:
Returns:
list: A list containing a single ProbeDataset object.
"""
prompts = list(iterator)
tokens = count_words_in_list(prompts)
prompts = list(iterator) if not lazy else iterator
tokens = count_words_in_list(prompts) if not lazy else 0
dataset = ProbeDataset(
dataset_name=name, metadata={}, prompts=prompts, tokens=tokens, approx_cost=0.0
dataset_name=name,
metadata={},
prompts=prompts,
tokens=tokens,
approx_cost=0.0,
lazy=lazy,
)
return [dataset]
@@ -0,0 +1,45 @@
import subprocess
import os
import asyncio
from loguru import logger
import asyncio
class Module:
def __init__(self, prompt_groups: [], tools_inbox: asyncio.Queue):
self.tools_inbox = tools_inbox
async def apply(self) -> []:
env = os.environ.copy()
env["OPENAI_API_BASE"] = "http://0.0.0.0:8718/proxy"
# Command to be executed
command = [
"python3",
"-m",
"garak",
"--model_type",
"openai",
"--model_name",
"gpt-3.5-turbo",
"--probes",
"encoding",
]
logger.info(f"Executing command: {command}")
# Execute the command with the specific environment
process = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, env=env
)
out, err = await asyncio.to_thread(process.communicate)
is_empty = self.tools_inbox.empty()
logger.info(f"Is inbox empty? {is_empty}")
while not self.tools_inbox.empty():
ref = self.tools_inbox.get_nowait()
message, _, ready = ref["message"], ref["reply"], ref["ready"]
yield message
ready.set()
logger.info("Garak tool finished.")
logger.info(f"stdout: {out}")
logger.error(f"exit code: {process.returncode}")