mirror of
https://github.com/msoedov/agentic_security.git
synced 2026-09-30 19:59:34 +02:00
feat(add Inspect AI):
This commit is contained in:
1 parent
9c4828f259
commit
cc5ea04205
8 files changed
+154
-21
No files matched your search
@@ -5,3 +5,4 @@ __pycache__/
|
|||||||
failures.csv
|
failures.csv
|
||||||
runs/
|
runs/
|
||||||
*.todo
|
*.todo
|
||||||
|
logs/
|
||||||
+48
-18
@@ -1,14 +1,15 @@
|
|||||||
|
import logging
|
||||||
import random
|
import random
|
||||||
import sys
|
|
||||||
from asyncio import Event, Queue
|
from asyncio import Event, Queue
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from fastapi import BackgroundTasks, FastAPI, HTTPException, Response
|
from fastapi import BackgroundTasks, FastAPI, HTTPException, Request, Response
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import FileResponse, StreamingResponse
|
from fastapi.responses import FileResponse, StreamingResponse
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||||||
|
|
||||||
from .http_spec import LLMSpec
|
from .http_spec import LLMSpec
|
||||||
from .probe_actor import fuzzer
|
from .probe_actor import fuzzer
|
||||||
@@ -16,15 +17,6 @@ from .probe_actor.refusal import REFUSAL_MARKS
|
|||||||
from .probe_data import REGISTRY
|
from .probe_data import REGISTRY
|
||||||
from .report_chart import plot_security_report
|
from .report_chart import plot_security_report
|
||||||
|
|
||||||
logger.remove(0)
|
|
||||||
logger.add(
|
|
||||||
sys.stderr,
|
|
||||||
format="<green>[{level}]</green> <blue>{time:YYYY-MM-DD HH:mm:ss.SS}</blue> | <cyan>{module}:{function}:{line}</cyan> | <white>{message}</white>",
|
|
||||||
colorize=True,
|
|
||||||
level="INFO",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Create the FastAPI app instance
|
# Create the FastAPI app instance
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
origins = [
|
origins = [
|
||||||
@@ -164,13 +156,13 @@ class Message(BaseModel):
|
|||||||
class CompletionRequest(BaseModel):
|
class CompletionRequest(BaseModel):
|
||||||
model: str
|
model: str
|
||||||
messages: list[Message]
|
messages: list[Message]
|
||||||
temperature: float
|
temperature: float = 0.7 # Default value for temperature
|
||||||
top_p: float
|
top_p: float = 1.0 # Default value for top_p
|
||||||
n: int
|
n: int = 1 # Default value for n
|
||||||
stop: list[str]
|
stop: list[str] = None # Optional; specify as None if not provided
|
||||||
max_tokens: int
|
max_tokens: int = 100 # Default value for max_tokens
|
||||||
presence_penalty: float
|
presence_penalty: float = 0.0 # Default value for presence_penalty
|
||||||
frequency_penalty: float
|
frequency_penalty: float = 0.0 # Default value for frequency_penalty
|
||||||
|
|
||||||
|
|
||||||
# OpenAI proxy endpoint
|
# OpenAI proxy endpoint
|
||||||
@@ -206,3 +198,41 @@ async def proxy_completions(request: CompletionRequest):
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
logging.config.dictConfig(
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"disable_existing_loggers": True,
|
||||||
|
"handlers": {
|
||||||
|
"console": {
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"handlers": ["console"],
|
||||||
|
"level": "INFO",
|
||||||
|
},
|
||||||
|
"loggers": {
|
||||||
|
"uvicorn.access": {
|
||||||
|
"level": "ERROR", # Set higher log level to suppress info logs globally
|
||||||
|
"handlers": ["console"],
|
||||||
|
"propagate": False,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LogNon200ResponsesMiddleware(BaseHTTPMiddleware):
|
||||||
|
async def dispatch(self, request: Request, call_next):
|
||||||
|
response = await call_next(request)
|
||||||
|
if response.status_code != 200:
|
||||||
|
logger.error(
|
||||||
|
f"{request.method} {request.url} - Status code: {response.status_code}"
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
# Add middleware to the application
|
||||||
|
app.add_middleware(LogNon200ResponsesMiddleware)
|
||||||
@@ -141,6 +141,16 @@ REGISTRY = [
|
|||||||
"url": "https://github.com/leondz/garak2",
|
"url": "https://github.com/leondz/garak2",
|
||||||
"dynamic": True,
|
"dynamic": True,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dataset_name": "InspectAI",
|
||||||
|
"num_prompts": 0,
|
||||||
|
"tokens": 0,
|
||||||
|
"approx_cost": 0.0,
|
||||||
|
"source": "Github: https://github.com/UKGovernmentBEIS/inspect_ai",
|
||||||
|
"selected": False,
|
||||||
|
"url": "https://github.com/UKGovernmentBEIS/inspect_ai",
|
||||||
|
"dynamic": True,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dataset_name": "Custom CSV",
|
"dataset_name": "Custom CSV",
|
||||||
"num_prompts": len(load_local_csv().prompts),
|
"num_prompts": len(load_local_csv().prompts),
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ import pandas as pd
|
|||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from agentic_security.probe_data import stenography_fn
|
from agentic_security.probe_data import stenography_fn
|
||||||
from agentic_security.probe_data.modules import adaptive_attacks, garak_tool
|
from agentic_security.probe_data.modules import (
|
||||||
|
adaptive_attacks,
|
||||||
|
garak_tool,
|
||||||
|
inspect_ai_tool,
|
||||||
|
)
|
||||||
|
|
||||||
IS_VERCEL = os.getenv("IS_VERCEL", "f") == "t"
|
IS_VERCEL = os.getenv("IS_VERCEL", "f") == "t"
|
||||||
|
|
||||||
@@ -206,6 +210,11 @@ def prepare_prompts(dataset_names, budget, tools_inbox=None):
|
|||||||
garak_tool.Module(group, tools_inbox=tools_inbox).apply(),
|
garak_tool.Module(group, tools_inbox=tools_inbox).apply(),
|
||||||
lazy=True,
|
lazy=True,
|
||||||
),
|
),
|
||||||
|
"InspectAI": lambda: dataset_from_iterator(
|
||||||
|
"InspectAI",
|
||||||
|
inspect_ai_tool.Module(group, tools_inbox=tools_inbox).apply(),
|
||||||
|
lazy=True,
|
||||||
|
),
|
||||||
"GPT fuzzer": lambda: [],
|
"GPT fuzzer": lambda: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ from loguru import logger
|
|||||||
|
|
||||||
|
|
||||||
class Module:
|
class Module:
|
||||||
|
|
||||||
def __init__(self, prompt_groups: [], tools_inbox: asyncio.Queue):
|
def __init__(self, prompt_groups: [], tools_inbox: asyncio.Queue):
|
||||||
self.tools_inbox = tools_inbox
|
self.tools_inbox = tools_inbox
|
||||||
if not self.is_garak_installed():
|
if not self.is_garak_installed():
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
from inspect_ai import Task, eval, task
|
||||||
|
from inspect_ai.dataset import example_dataset
|
||||||
|
from inspect_ai.scorer import model_graded_fact
|
||||||
|
from inspect_ai.solver import chain_of_thought, generate, self_critique
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def theory_of_mind():
|
||||||
|
return Task(
|
||||||
|
dataset=example_dataset("theory_of_mind"),
|
||||||
|
plan=[chain_of_thought(), generate(), self_critique()],
|
||||||
|
scorer=model_graded_fact(),
|
||||||
|
)
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import asyncio
|
||||||
|
import importlib.util
|
||||||
|
import os
|
||||||
|
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
inspect_ai_task = (
|
||||||
|
__file__.replace("inspect_ai_tool.py", "inspect_ai_task.py")
|
||||||
|
.replace(os.getcwd(), "")
|
||||||
|
.strip("/")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Module:
|
||||||
|
name = "Inspect AI"
|
||||||
|
|
||||||
|
def __init__(self, prompt_groups: [], tools_inbox: asyncio.Queue):
|
||||||
|
self.tools_inbox = tools_inbox
|
||||||
|
if not self.is_tool_installed():
|
||||||
|
logger.error(
|
||||||
|
"inspect_ai module is not installed. Please install it using 'pip install inspect_ai'"
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_tool_installed(self) -> bool:
|
||||||
|
inspect_ai = importlib.util.find_spec("inspect_ai")
|
||||||
|
return inspect_ai is not None
|
||||||
|
|
||||||
|
async def _proc(self, command):
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["OPENAI_API_BASE"] = "http://0.0.0.0:8718/proxy"
|
||||||
|
process = await asyncio.create_subprocess_shell(
|
||||||
|
command,
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.PIPE,
|
||||||
|
env=env,
|
||||||
|
shell=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(f"Started {command}")
|
||||||
|
|
||||||
|
# Read output as it becomes available
|
||||||
|
async for line in process.stdout:
|
||||||
|
logger.info(line.decode().strip())
|
||||||
|
|
||||||
|
# Check for errors
|
||||||
|
err = await process.stderr.read()
|
||||||
|
if err:
|
||||||
|
logger.error(err.decode().strip())
|
||||||
|
|
||||||
|
await process.wait()
|
||||||
|
logger.info(f"Command {command} {process}finished.")
|
||||||
|
|
||||||
|
async def apply(self) -> []:
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["OPENAI_API_BASE"] = "http://0.0.0.0:8718/proxy"
|
||||||
|
|
||||||
|
# Command to be executed
|
||||||
|
command = f"inspect eval {inspect_ai_task} --model openai/gpt-4 --model-base-url=http://0.0.0.0:8718/proxy"
|
||||||
|
logger.info(f"Executing command: {command}")
|
||||||
|
|
||||||
|
proc = asyncio.create_task(self._proc(command))
|
||||||
|
is_empty = self.tools_inbox.empty()
|
||||||
|
await asyncio.sleep(2)
|
||||||
|
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(f"{self.name} tool finished.")
|
||||||
|
await proc
|
||||||
Reference in new issue
Block a user