Compare commits

...

23 Commits

Author SHA1 Message Date
Alexander Myasoedov 8146aef2cb feat(Bump version): 2025-02-15 13:35:53 +02:00
Alexander Myasoedov a20c19507d feat(add changelog sh): 2025-02-15 13:35:36 +02:00
Alexander Myasoedov 998c000cb3 feat(update fast api): 2025-02-15 13:30:50 +02:00
Alexander Myasoedov 99b82ef052 feat(update deps): 2025-02-15 13:29:19 +02:00
Alexander Myasoedov 32547535b9 Merge branch 'main' of github.com:msoedov/agentic_security 2025-02-14 21:08:40 +02:00
Alexander Myasoedov c4f039258a Merge pull request #126 from msoedov/dependabot/pip/mkdocstrings-0.28.1
build(deps-dev): bump mkdocstrings from 0.27.0 to 0.28.1
2025-02-14 21:02:21 +02:00
dependabot[bot] 5cfaac7069 build(deps-dev): bump mkdocstrings from 0.27.0 to 0.28.1
Bumps [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings) from 0.27.0 to 0.28.1.
- [Release notes](https://github.com/mkdocstrings/mkdocstrings/releases)
- [Changelog](https://github.com/mkdocstrings/mkdocstrings/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mkdocstrings/mkdocstrings/compare/0.27.0...0.28.1)

---
updated-dependencies:
- dependency-name: mkdocstrings
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-14 17:53:41 +00:00
Alexander Myasoedov 38e3bca49b feat(Add discord link): 2025-02-14 19:38:13 +02:00
Alexander Myasoedov b06eca4e84 fix(tests): 2025-02-14 11:44:24 +02:00
Alexander Myasoedov 4ef7473a56 feat(add scan-csv api route): 2025-02-14 11:40:55 +02:00
Alexander Myasoedov 0987f05c4d feat(add IntegrationProto): 2025-02-14 11:20:53 +02:00
Alexander Myasoedov f0fb95828a feat(add integrations module): 2025-02-14 11:16:01 +02:00
Alexander Myasoedov 05021e59f1 feat(improve audio modality generation): 2025-02-14 11:15:11 +02:00
Alexander Myasoedov 3ae4f34bdf feat(add more image generation variants): 2025-02-14 11:10:37 +02:00
Alexander Myasoedov 1ba6c588d7 fix(add exlude rules): 2025-02-14 01:43:41 +02:00
Alexander Myasoedov 0a0251f451 fix(readme): 2025-02-14 01:40:16 +02:00
Alexander Myasoedov df848f8a79 fix(disable pycln): 2025-02-11 15:40:36 +02:00
Alexander Myasoedov 4ac912c5e5 fix(docs): 2025-02-11 15:38:04 +02:00
Alexander Myasoedov 2ff397bffb fix(git ignore): 2025-02-11 15:36:14 +02:00
Alexander Myasoedov e03264d083 fix(pre commit): 2025-02-11 15:35:37 +02:00
Alexander Myasoedov 851a0f03a8 feat(docs + pre commit): 2025-02-11 15:34:12 +02:00
Alexander Myasoedov 152c87611f feat(minor doc updates): 2025-02-11 15:26:31 +02:00
Alexander Myasoedov 5fa33f094c feat(add cost module): 2025-02-09 22:01:57 +02:00
24 changed files with 712 additions and 72 deletions
+44 -1
View File
@@ -1,2 +1,45 @@
.git/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# Distribution / packaging
build/
dist/
*.egg-info/
# Virtual environments
.venv/
env/
ENV/
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# PyInstaller
*.spec
# macOS specific files
.DS_Store
# Windows specific files
Thumbs.db
desktop.ini
# Tools and editors
.idea/
.vscode/
cmder/
# Output directories
Output/
te/
+21
View File
@@ -0,0 +1,21 @@
name: Pre-Commit Checks
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install pre-commit
run: pip install pre-commit
- name: Run pre-commit
run: pre-commit run --all-files
+5
View File
@@ -11,3 +11,8 @@ sandbox.py
site/
agesec.toml
.clinerules
garak_rest.json
2025.*.json
inv/
scripts/
docx/
+8 -4
View File
@@ -43,6 +43,10 @@ repos:
- id: check-shebang-scripts-are-executable
- id: check-added-large-files
args: ['--maxkb=100']
- id: trailing-whitespace
types: [python]
- id: end-of-file-fixer
types: [python]
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.17
@@ -52,10 +56,10 @@ repos:
entry: mdformat .
language_version: python3.11
- repo: https://github.com/hadialqattan/pycln
rev: v2.4.0
hooks:
- id: pycln
# - repo: https://github.com/hadialqattan/pycln
# rev: v2.4.0
# hooks:
# - id: pycln
- repo: https://github.com/isidentical/teyit
rev: 0.4.3
+4
View File
@@ -21,6 +21,10 @@ RUN pip install --no-cache-dir -r requirements.txt
# Runtime stage
FROM python:3.11-slim
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
# Copy only the necessary files from the builder stage
+17 -12
View File
@@ -6,25 +6,30 @@
The open-source Agentic LLM Vulnerability Scanner
<br />
<br />
<p>
<img alt="GitHub Contributors" src="https://img.shields.io/github/contributors/msoedov/agentic_security" />
<img alt="GitHub Last Commit" src="https://img.shields.io/github/last-commit/msoedov/agentic_security" />
<img alt="" src="https://img.shields.io/github/repo-size/msoedov/agentic_security" />
<img alt="Downloads" src="https://static.pepy.tech/badge/agentic_security" />
<img alt="GitHub Issues" src="https://img.shields.io/github/issues/msoedov/agentic_security" />
<img alt="GitHub Pull Requests" src="https://img.shields.io/github/issues-pr/msoedov/agentic_security" />
<img alt="Github License" src="https://img.shields.io/github/license/msoedov/agentic_security" />
</p>
</p>
<p align="center">
<a href="https://github.com/msoedov/agentic_security/commits/main">
<img alt="GitHub Last Commit" src="https://img.shields.io/github/last-commit/msoedov/agentic_security?style=for-the-badge&logo=git&labelColor=000000&logoColor=FFFFFF&label=Last Commit&color=6A35FF" />
</a>
<a href="https://github.com/msoedov/agentic_security">
<img alt="GitHub Repo Size" src="https://img.shields.io/github/repo-size/msoedov/agentic_security?style=for-the-badge&logo=database&labelColor=000000&logoColor=FFFFFF&label=Repo Size&color=yellow" />
</a>
</a>
<a href="https://github.com/msoedov/agentic_security/blob/master/LICENSE">
<img alt="GitHub License" src="https://img.shields.io/github/license/msoedov/agentic_security?style=for-the-badge&logo=codeigniter&labelColor=000000&logoColor=FFFFFF&label=License&color=FFCC19" />
</a>
<a href="https://discord.com/channels/1340010688764051499/1340010689309315247"><img alt="Join the community" src="https://img.shields.io/badge/Join%20the%20community-black.svg?style=for-the-badge&logo=lightning&labelColor=000000&logoColor=FFFFFF&label=&color=DD55FF&logoWidth=20" /></a>
</p>
## Features
- Customizable Rule Sets or Agent based attacks🛠️
- Multi modal attacks and vulnerability scanners🛠️
- Multi-Step/multi-round Jailbreaks 🌀
- Comprehensive fuzzing for any LLMs 🧪
- LLM API integration and stress testing 🛠️
- Wide range of fuzzing and attack techniques 🌀
- RL based attacks 📡
Note: Please be aware that Agentic Security is designed as a safety scanner tool and not a foolproof solution. It cannot guarantee complete protection against all possible threats.
+12
View File
@@ -0,0 +1,12 @@
import asyncio
from typing import Protocol
class IntegrationProto(Protocol):
def __init__(
self, prompt_groups: list, tools_inbox: asyncio.Queue, opts: dict = {}
):
...
async def apply(self) -> list:
...
@@ -0,0 +1,58 @@
def calculate_cost(tokens: int, model: str = "deepseek-chat") -> float:
"""Calculate API cost based on token count and model.
Args:
tokens (int): Number of tokens used
model (str): Model name to calculate cost for
Returns:
float: Cost in USD
"""
# API pricing as of 2024-03-01
pricing = {
"deepseek-chat": {
"input": 0.0007 / 1000, # $0.70 per million input tokens
"output": 0.0028 / 1000, # $2.80 per million output tokens
},
"gpt-4-turbo": {
"input": 0.01 / 1000, # $10 per million input tokens
"output": 0.03 / 1000, # $30 per million output tokens
},
"gpt-4": {
"input": 0.03 / 1000, # $30 per million input tokens
"output": 0.06 / 1000, # $60 per million output tokens
},
"gpt-3.5-turbo": {
"input": 0.0015 / 1000, # $1.50 per million input tokens
"output": 0.002 / 1000, # $2.00 per million output tokens
},
"claude-3-opus": {
"input": 0.015 / 1000, # $15 per million input tokens
"output": 0.075 / 1000, # $75 per million output tokens
},
"claude-3-sonnet": {
"input": 0.003 / 1000, # $3 per million input tokens
"output": 0.015 / 1000, # $15 per million output tokens
},
"claude-3-haiku": {
"input": 0.00025 / 1000, # $0.25 per million input tokens
"output": 0.00125 / 1000, # $1.25 per million output tokens
},
"mistral-large": {
"input": 0.008 / 1000, # $8 per million input tokens
"output": 0.024 / 1000, # $24 per million output tokens
},
"mixtral-8x7b": {
"input": 0.002 / 1000, # $2 per million input tokens
"output": 0.006 / 1000, # $6 per million output tokens
},
}
if model not in pricing:
raise ValueError(f"Unknown model: {model}")
# For now, assume 1:1 input/output ratio
input_cost = tokens * pricing[model]["input"]
output_cost = tokens * pricing[model]["output"]
return round(input_cost + output_cost, 4)
+3 -4
View File
@@ -10,6 +10,7 @@ from skopt.space import Real
from agentic_security.http_spec import Modality
from agentic_security.models.schemas import Scan, ScanResult
from agentic_security.probe_actor.cost_module import calculate_cost
from agentic_security.probe_actor.refusal import refusal_heuristic
from agentic_security.probe_data import audio_generator, image_generator, msj_data
from agentic_security.probe_data.data import prepare_prompts
@@ -38,8 +39,6 @@ def multi_modality_spec(llm_spec):
return llm_spec
case _:
return llm_spec
# case _:
# raise NotImplementedError(f"Modality {llm_spec.modality} not supported yet")
async def process_prompt(
@@ -143,7 +142,7 @@ async def perform_single_shot_scan(
module_failures += 1
failure_rate = module_failures / max(processed_prompts, 1)
failure_rates.append(failure_rate)
cost = round(tokens * 1.5 / 1000_000, 2)
cost = calculate_cost(tokens)
yield ScanResult(
module=module.dataset_name,
@@ -274,7 +273,7 @@ async def perform_many_shot_scan(
failure_rate = module_failures / max(processed_prompts, 1)
failure_rates.append(failure_rate)
cost = round(tokens * 1.5 / 1000_000, 2)
cost = calculate_cost(tokens)
yield ScanResult(
module=module.dataset_name,
+30 -2
View File
@@ -52,11 +52,37 @@ def generate_audio_mac_wav(prompt: str) -> bytes:
return audio_bytes
def generate_audio_cross_platform(prompt: str) -> bytes:
"""
Generate an audio file from the provided prompt using gTTS for cross-platform support.
Parameters:
prompt (str): Text to convert into audio.
Returns:
bytes: The audio data in MP3 format.
"""
from gtts import gTTS # Import gTTS for cross-platform support
tts = gTTS(text=prompt, lang="en")
temp_mp3_path = f"temp_audio_{uuid.uuid4().hex}.mp3"
tts.save(temp_mp3_path)
try:
with open(temp_mp3_path, "rb") as f:
audio_bytes = f.read()
finally:
if os.path.exists(temp_mp3_path):
os.remove(temp_mp3_path)
return audio_bytes
@cache_to_disk()
def generate_audioform(prompt: str) -> bytes:
"""
Generate an audio file from the provided prompt in WAV format.
Uses macOS 'say' command if the operating system is macOS.
Uses macOS 'say' command if the operating system is macOS, otherwise uses gTTS.
Parameters:
prompt (str): Text to convert into audio.
@@ -67,9 +93,11 @@ def generate_audioform(prompt: str) -> bytes:
current_os = platform.system()
if current_os == "Darwin": # macOS
return generate_audio_mac_wav(prompt)
elif current_os in ["Windows", "Linux"]:
return generate_audio_cross_platform(prompt)
else:
raise NotImplementedError(
"Audio generation is only supported on macOS for now."
"Audio generation is only supported on macOS, Windows, and Linux for now."
)
+52 -13
View File
@@ -38,12 +38,13 @@ def generate_image_dataset(
@cache_to_disk()
def generate_image(prompt: str) -> bytes:
def generate_image(prompt: str, variant: int = 0) -> bytes:
"""
Generate an image based on the provided prompt and return it as bytes.
Parameters:
prompt (str): Text to display on the generated image.
variant (int): The variant style of the image.
Returns:
bytes: The image data in JPG format.
@@ -51,18 +52,56 @@ def generate_image(prompt: str) -> bytes:
# Create a matplotlib figure
fig, ax = plt.subplots(figsize=(6, 4))
# Customize the plot (background color, text, etc.)
ax.set_facecolor("lightblue")
ax.text(
0.5,
0.5,
prompt,
fontsize=16,
ha="center",
va="center",
wrap=True,
color="darkblue",
)
# Customize the plot based on the variant
if variant == 1:
# Dark Theme
ax.set_facecolor("darkgray")
text_color = "white"
fontsize = 18
elif variant == 2:
# Artistic Theme
ax.set_facecolor("lightpink")
text_color = "black"
fontsize = 20
# Add a border around the text
ax.text(
0.5,
0.5,
prompt,
fontsize=fontsize,
ha="center",
va="center",
wrap=True,
color=text_color,
bbox=dict(
facecolor="lightyellow", edgecolor="black", boxstyle="round,pad=0.5"
),
)
elif variant == 3:
# Minimalist Theme
ax.set_facecolor("white")
text_color = "black"
fontsize = 14
# Add a simple geometric shape (circle) behind the text
circle = plt.Circle((0.5, 0.5), 0.3, color="lightblue", fill=True)
ax.add_artist(circle)
else:
# Default Theme
ax.set_facecolor("lightblue")
text_color = "darkblue"
fontsize = 16
if variant != 2:
ax.text(
0.5,
0.5,
prompt,
fontsize=fontsize,
ha="center",
va="center",
wrap=True,
color=text_color,
)
# Remove axes for a cleaner look
ax.axis("off")
@@ -3,6 +3,7 @@ import platform
import pytest
from agentic_security.probe_data.audio_generator import (
generate_audio_cross_platform,
generate_audio_mac_wav,
generate_audioform,
)
@@ -24,6 +25,13 @@ def test_generate_audioform_mac():
audio_bytes = generate_audioform(prompt)
assert isinstance(audio_bytes, bytes)
assert len(audio_bytes) > 0
def test_generate_audio_cross_platform():
if platform.system() in ["Windows", "Linux"]:
prompt = "This is a cross-platform test."
audio_bytes = generate_audio_cross_platform(prompt)
assert isinstance(audio_bytes, bytes)
assert len(audio_bytes) > 0
else:
with pytest.raises(NotImplementedError):
generate_audioform("This should raise an error on non-macOS systems.")
pytest.skip("Test is only applicable on Windows and Linux.")
@@ -1,5 +1,7 @@
from unittest.mock import patch
import pytest
from agentic_security.probe_data.image_generator import (
generate_image,
generate_image_dataset,
@@ -7,9 +9,10 @@ from agentic_security.probe_data.image_generator import (
from agentic_security.probe_data.models import ImageProbeDataset, ProbeDataset
def test_generate_image():
@pytest.mark.parametrize("variant", [0, 1, 2, 3])
def test_generate_image(variant):
prompt = "Test prompt"
image_bytes = generate_image(prompt)
image_bytes = generate_image(prompt, variant)
assert isinstance(image_bytes, bytes)
assert len(image_bytes) > 0
+26 -1
View File
@@ -1,6 +1,6 @@
from datetime import datetime
from fastapi import APIRouter, BackgroundTasks, HTTPException
from fastapi import APIRouter, BackgroundTasks, File, HTTPException, Query, UploadFile
from fastapi.responses import StreamingResponse
from ..core.app import get_stop_event, get_tools_inbox, set_current_run
@@ -52,3 +52,28 @@ async def scan(scan_parameters: Scan, background_tasks: BackgroundTasks):
async def stop_scan():
get_stop_event().set()
return {"status": "Scan stopped"}
@router.post("/scan-csv")
async def scan_csv(
background_tasks: BackgroundTasks,
file: UploadFile = File(...),
llmSpec: UploadFile = File(...),
optimize: bool = Query(False),
maxBudget: int = Query(10_000),
enableMultiStepAttack: bool = Query(False),
):
# TODO: content dataset to fuzzer
content = await file.read() # noqa
llm_spec = await llmSpec.read()
scan_parameters = Scan(
llmSpec=llm_spec,
optimize=optimize,
maxBudget=1000,
enableMultiStepAttack=enableMultiStepAttack,
)
return StreamingResponse(
streaming_response_generator(scan_parameters), media_type="application/json"
)
+22
View File
@@ -0,0 +1,22 @@
from fastapi.testclient import TestClient
import agentic_security.test_spec_assets as test_spec_assets
from agentic_security.routes.scan import router
client = TestClient(router)
def test_upload_csv_and_run():
# Create a sample CSV content
csv_content = "id,prompt\nspec1,value1\nspec2,value3"
# Send a POST request to the /upload-csv endpoint
response = client.post(
"/scan-csv?optimize=false&enableMultiStepAttack=false&maxBudget=1000",
files={
"file": ("test.csv", csv_content, "text/csv"),
"llmSpec": ("spec.txt", test_spec_assets.SAMPLE_SPEC, "text/plain"),
},
)
assert response.status_code == 200
assert "Scan completed." in response.text
+1 -1
View File
@@ -437,7 +437,7 @@
<th class="p-3">Vulnerability Module</th>
<th class="p-3">% Strength</th>
<th class="p-3">Number of Tokens</th>
<th class="p-3">Cost (in gpt-3 tokens)</th>
<th class="p-3">Approx Cost (in tokens)</th>
</tr>
</thead>
<tbody>
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
# Get the last tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null)
if [ -z "$LAST_TAG" ]; then
echo "No tags found. Retrieving all commits."
LOG_RANGE="HEAD"
else
echo "Generating changelog from last tag: $LAST_TAG"
LOG_RANGE="$LAST_TAG..HEAD"
fi
# Retrieve commit messages excluding merge commits and format them with author names and stripped email domain as nickname
CHANGELOG=$(git log --pretty=format:"- %s by %an, @%ae)" --no-merges $LOG_RANGE | sed -E 's/@([^@]+)@([^@]+)\..*/@\1/')
# Output the changelog
if [ -n "$CHANGELOG" ]; then
echo "# Changelog"
echo "
## Changes since $LAST_TAG"
echo "$CHANGELOG"
else
echo "No new commits since last tag."
fi
+55
View File
@@ -0,0 +1,55 @@
# Abstractions in Agentic Security
This document outlines the key abstractions used in the Agentic Security project, providing insights into the classes, interfaces, and design patterns that form the backbone of the system.
## Key Abstractions
### AgentSpecification
- **Purpose**: Defines the specification for a language model or agent, including its name, version, description, capabilities, and configuration settings.
- **Usage**: Used to initialize and configure the `OperatorToolBox` and other components that interact with language models.
### OperatorToolBox
- **Purpose**: Serves as the main class for managing dataset operations, including validation, execution, and result retrieval.
- **Methods**:
- `get_spec()`: Returns the agent specification.
- `get_datasets()`: Retrieves the datasets for operations.
- `validate()`: Validates the toolbox setup.
- `run_operation(operation: str)`: Executes a specified operation.
### DatasetManagerAgent
- **Purpose**: Provides tools for managing and executing operations on datasets through an agent-based approach.
- **Tools**:
- `validate_toolbox`: Validates the `OperatorToolBox`.
- `execute_operation`: Executes operations on datasets.
- `retrieve_results`: Retrieves operation results.
- `retrieve_failures`: Retrieves any failures encountered.
### ProbeDataset
- **Purpose**: Represents a dataset used in security scans, including metadata, prompts, and associated costs.
- **Methods**:
- `metadata_summary()`: Provides a summary of the dataset's metadata.
### Refusal Classifier
- **Purpose**: Analyzes responses from language models to detect potential security vulnerabilities.
- **Design**: Utilizes predefined rules and machine learning models for classification.
## Design Patterns
### Modular Architecture
- **Description**: The system is designed with a modular architecture, allowing for easy integration of new components and features.
- **Benefits**: Enhances flexibility, extensibility, and scalability.
### Agent-Based Design
- **Description**: Utilizes an agent-based approach for managing and executing operations on datasets.
- **Benefits**: Provides a structured framework for interacting with language models and datasets.
## Conclusion
The abstractions in Agentic Security are designed to provide a flexible and extensible framework for managing and executing security scans on language models. This document highlights the key classes, interfaces, and design patterns that contribute to the system's architecture and functionality.
+51
View File
@@ -0,0 +1,51 @@
# Design Document
This document provides an overview of the design and architecture of the Agentic Security project. It outlines the key components, their interactions, and the design principles guiding the development of the system.
## Overview
Agentic Security is an open-source LLM vulnerability scanner designed to identify and mitigate potential security threats in language models. It integrates various modules and datasets to perform comprehensive security scans.
## Architecture
The system is built around a modular architecture, allowing for flexibility and extensibility. The core components include:
- **Agentic Security Core**: The main application responsible for orchestrating the security scans and managing interactions with external modules.
- **Probe Actor**: Handles the execution of fuzzing and attack techniques on language models.
- **Probe Data**: Manages datasets used for testing and validation, including loading and processing data.
- **Refusal Classifier**: Analyzes responses from language models to identify potential security issues.
## Key Components
### Agentic Security Core
The core application is responsible for initializing the system, managing configurations, and coordinating the execution of security scans. It provides a command-line interface for users to interact with the system.
### Probe Actor
The Probe Actor module implements various fuzzing and attack techniques. It is designed to test the robustness of language models by simulating different attack scenarios.
### Probe Data
The Probe Data module manages datasets used in security scans. It supports loading data from local files and external sources, providing a flexible framework for testing different scenarios.
### Refusal Classifier
The Refusal Classifier analyzes responses from language models to detect potential security vulnerabilities. It uses predefined rules and machine learning models to classify responses.
## Design Principles
- **Modularity**: The system is designed to be modular, allowing for easy integration of new components and features.
- **Extensibility**: New modules and datasets can be added to the system without significant changes to the core architecture.
- **Scalability**: The system is built to handle large datasets and complex security scans efficiently.
## Interaction Flow
1. **Initialization**: The system is initialized with the necessary configurations and datasets.
1. **Execution**: The Probe Actor executes security scans on the language models using the datasets provided by the Probe Data module.
1. **Analysis**: The Refusal Classifier analyzes the responses to identify potential security issues.
1. **Reporting**: Results are compiled and presented to the user, highlighting any vulnerabilities detected.
## Conclusion
The design of Agentic Security emphasizes flexibility, extensibility, and scalability, providing a robust framework for identifying and mitigating security threats in language models. This document serves as a guide to understanding the system's architecture and key components.
+123
View File
@@ -0,0 +1,123 @@
# Operator Module
The `operator.py` module provides tools for managing and operating on datasets using an agent-based approach. It is designed to facilitate the execution of operations on datasets through a structured and validated process.
## Classes
### AgentSpecification
Defines the specification for an LLM/agent:
- `name`: Name of the LLM/agent
- `version`: Version of the LLM/agent
- `description`: Description of the LLM/agent
- `capabilities`: List of capabilities
- `configuration`: Configuration settings
### OperatorToolBox
Main class for dataset operations:
- `__init__(spec: AgentSpecification, datasets: list[dict[str, Any]])`: Initialize with agent spec and datasets. This sets up the toolbox with the necessary specifications and datasets for operation.
- `get_spec()`: Get the agent specification. Returns the `AgentSpecification` object associated with the toolbox.
- `get_datasets()`: Get the datasets. Returns a list of datasets that the toolbox operates on.
- `validate()`: Validate the toolbox. Checks if the toolbox is correctly set up with valid specifications and datasets.
- `stop()`: Stop the toolbox. Halts any ongoing operations within the toolbox.
- `run()`: Run the toolbox. Initiates the execution of operations as defined in the toolbox.
- `get_results()`: Get operation results. Retrieves the results of operations performed by the toolbox.
- `get_failures()`: Get failures. Provides a list of any failures encountered during operations.
- `run_operation(operation: str)`: Run a specific operation. Executes a given operation on the datasets, returning the result or failure message.
## Agent Tools
The `dataset_manager_agent` provides these tools:
### validate_toolbox
Validates the OperatorToolBox:
```python
@dataset_manager_agent.tool
async def validate_toolbox(ctx: RunContext[OperatorToolBox]) -> str
```
### execute_operation
Executes an operation on a dataset:
```python
@dataset_manager_agent.tool
async def execute_operation(ctx: RunContext[OperatorToolBox], operation: str) -> str
```
### retrieve_results
Retrieves operation results:
```python
@dataset_manager_agent.tool
async def retrieve_results(ctx: RunContext[OperatorToolBox]) -> str
```
### retrieve_failures
Retrieves failures:
```python
@dataset_manager_agent.tool
async def retrieve_failures(ctx: RunContext[OperatorToolBox]) -> str
```
## Usage Examples
### Initializing the OperatorToolBox
To initialize the `OperatorToolBox`, you need to provide an `AgentSpecification` and a list of datasets:
```python
spec = AgentSpecification(
name="GPT-4",
version="4.0",
description="A powerful language model",
capabilities=["text-generation", "question-answering"],
configuration={"max_tokens": 100},
)
datasets = [{"name": "dataset1"}, {"name": "dataset2"}]
toolbox = OperatorToolBox(spec=spec, datasets=datasets)
```
### Synchronous Usage
```python
def run_dataset_manager_agent_sync():
prompts = [
"Validate the toolbox.",
"Execute operation on 'dataset2'.",
"Retrieve the results.",
"Retrieve any failures."
]
for prompt in prompts:
result = dataset_manager_agent.run_sync(prompt, deps=toolbox)
print(f"Response: {result.data}")
```
### Asynchronous Usage
```python
async def run_dataset_manager_agent_async():
prompts = [
"Validate the toolbox.",
"Execute operation on 'dataset2'.",
"Retrieve the results.",
"Retrieve any failures."
]
for prompt in prompts:
result = await dataset_manager_agent.run(prompt, deps=toolbox)
print(f"Response: {result.data}")
```
These updates provide a more detailed and comprehensive understanding of the `operator.py` module, its classes, and its usage.
+65
View File
@@ -0,0 +1,65 @@
# Quickstart Guide
Welcome to the Quickstart Guide for Agentic Security. This guide will help you set up and start using the project quickly.
## Installation
To get started with Agentic Security, install the package using pip:
```shell
pip install agentic_security
```
## Initial Setup
After installation, you can start the application using the following command:
```shell
agentic_security
```
This will initialize the server and prepare it for use.
## Basic Usage
To run the main application, use:
```shell
python -m agentic_security
```
You can also view help options with:
```shell
agentic_security --help
```
## Running as a CI Check
Initialize the configuration for CI checks:
```shell
agentic_security init
```
This will generate a default configuration file named `agesec.toml`.
## Additional Commands
- List available modules:
```shell
agentic_security ls
```
- Run a security scan:
```shell
agentic_security ci
```
## Further Information
For more detailed information, refer to the [Documentation](index.md) or the [API Reference](api_reference.md).
This quickstart guide should help you get up and running with Agentic Security efficiently.
+30 -4
View File
@@ -8,9 +8,13 @@ repo_name: msoedov/agentic_security
copyright: Maintained by <a href="https://msoedov.github.io">Agentic Security Team</a>.
nav:
- Home: index.md
- Adventure starts here:
- Overview: index.md
- Quickstart: quickstart.md
- Design: design.md
- Abstractions: abstractions.md
- Features: probe_data.md
- Core Concepts:
- Concepts:
- Probe Actor: probe_actor.md
- Refusal Actor: refusal_classifier_plugins.md
- Agent Spec: http_spec.md
@@ -26,10 +30,32 @@ nav:
- Image Generation: image_generation.md
- Stenography Functions: stenography.md
- Reinforcement Learning Optimization: rl_model.md
- WIP:
- Agent Operator: operator.md
- Reference:
- API Reference: api_reference.md
- Community:
- Contributing: contributing.md
# - Project:
# - Setup: setup.md
# - Version control: version_control.md
# - Docker: docker.md
# - Variables: variables.md
# - Custom libraries: custom_libraries.md
# - Database: database.md
# - Credentials: credentials.md
# - Code execution: code_execution.md
# - Settings: settings.md
# - Version upgrades: version_upgrades.md
# - Contributing:
# - Overview: contributing_overview.md
# - Dev environment: dev_environment.md
# - Backend: backend.md
# - Frontend: frontend.md
# - Documentation: documentation.md
# - About:
# - Code of conduct: code_of_conduct.md
# - Usage statistics: usage_statistics.md
# - FAQ: faq.md
# - Changelog: changelog.md
plugins:
- search
Generated
+40 -22
View File
@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "aiohappyeyeballs"
@@ -645,21 +645,21 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"]
[[package]]
name = "datasets"
version = "3.2.0"
version = "3.3.0"
description = "HuggingFace community-driven open-source library of datasets"
optional = false
python-versions = ">=3.9.0"
files = [
{file = "datasets-3.2.0-py3-none-any.whl", hash = "sha256:f3d2ba2698b7284a4518019658596a6a8bc79f31e51516524249d6c59cf0fe2a"},
{file = "datasets-3.2.0.tar.gz", hash = "sha256:9a6e1a356052866b5dbdd9c9eedb000bf3fc43d986e3584d9b028f4976937229"},
{file = "datasets-3.3.0-py3-none-any.whl", hash = "sha256:22312d09626f8fc3aa0a237b0c164997f5903bddd4c4c9e27dbaf563754c681b"},
{file = "datasets-3.3.0.tar.gz", hash = "sha256:54c607b06f6eaa1572e21e200d2870d89d50e3bcc622dc2021a53a6ce4f684c2"},
]
[package.dependencies]
aiohttp = "*"
dill = ">=0.3.0,<0.3.9"
filelock = "*"
fsspec = {version = ">=2023.1.0,<=2024.9.0", extras = ["http"]}
huggingface-hub = ">=0.23.0"
fsspec = {version = ">=2023.1.0,<=2024.12.0", extras = ["http"]}
huggingface-hub = ">=0.24.0"
multiprocess = "<0.70.17"
numpy = ">=1.17"
packaging = "*"
@@ -673,15 +673,15 @@ xxhash = "*"
[package.extras]
audio = ["librosa", "soundfile (>=0.12.1)", "soxr (>=0.4.0)"]
benchmarks = ["tensorflow (==2.12.0)", "torch (==2.0.1)", "transformers (==4.30.1)"]
dev = ["Pillow (>=9.4.0)", "absl-py", "decorator", "decord (==0.6.0)", "elasticsearch (>=7.17.12,<8.0.0)", "faiss-cpu (>=1.8.0.post1)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "moto[server]", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "ruff (>=0.3.0)", "s3fs", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "soxr (>=0.4.0)", "sqlalchemy", "tensorflow (>=2.16.0)", "tensorflow (>=2.6.0)", "tensorflow (>=2.6.0)", "tiktoken", "torch", "torch (>=2.0.0)", "torchdata", "transformers", "transformers (>=4.42.0)", "zstandard"]
dev = ["Pillow (>=9.4.0)", "absl-py", "decorator", "decord (==0.6.0)", "elasticsearch (>=7.17.12,<8.0.0)", "faiss-cpu (>=1.8.0.post1)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "moto[server]", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "ruff (>=0.3.0)", "s3fs", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "soundfile (>=0.12.1)", "soxr (>=0.4.0)", "sqlalchemy", "tensorflow (>=2.16.0)", "tensorflow (>=2.6.0)", "tensorflow (>=2.6.0)", "tiktoken", "torch", "torch (>=2.0.0)", "torchdata", "transformers", "transformers (>=4.42.0)", "zstandard"]
docs = ["s3fs", "tensorflow (>=2.6.0)", "torch", "transformers"]
jax = ["jax (>=0.3.14)", "jaxlib (>=0.3.14)"]
quality = ["ruff (>=0.3.0)"]
s3 = ["s3fs"]
tensorflow = ["tensorflow (>=2.6.0)"]
tensorflow-gpu = ["tensorflow (>=2.6.0)"]
tests = ["Pillow (>=9.4.0)", "absl-py", "decorator", "decord (==0.6.0)", "elasticsearch (>=7.17.12,<8.0.0)", "faiss-cpu (>=1.8.0.post1)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "moto[server]", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "soxr (>=0.4.0)", "sqlalchemy", "tensorflow (>=2.16.0)", "tensorflow (>=2.6.0)", "tiktoken", "torch (>=2.0.0)", "torchdata", "transformers (>=4.42.0)", "zstandard"]
tests-numpy2 = ["Pillow (>=9.4.0)", "absl-py", "decorator", "decord (==0.6.0)", "elasticsearch (>=7.17.12,<8.0.0)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "lz4", "moto[server]", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "soxr (>=0.4.0)", "sqlalchemy", "tiktoken", "torch (>=2.0.0)", "torchdata", "transformers (>=4.42.0)", "zstandard"]
tests = ["Pillow (>=9.4.0)", "absl-py", "decorator", "decord (==0.6.0)", "elasticsearch (>=7.17.12,<8.0.0)", "faiss-cpu (>=1.8.0.post1)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "moto[server]", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "soundfile (>=0.12.1)", "soxr (>=0.4.0)", "sqlalchemy", "tensorflow (>=2.16.0)", "tensorflow (>=2.6.0)", "tiktoken", "torch (>=2.0.0)", "torchdata", "transformers (>=4.42.0)", "zstandard"]
tests-numpy2 = ["Pillow (>=9.4.0)", "absl-py", "decorator", "decord (==0.6.0)", "elasticsearch (>=7.17.12,<8.0.0)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "lz4", "moto[server]", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "soundfile (>=0.12.1)", "soxr (>=0.4.0)", "sqlalchemy", "tiktoken", "torch (>=2.0.0)", "torchdata", "transformers (>=4.42.0)", "zstandard"]
torch = ["torch"]
vision = ["Pillow (>=9.4.0)"]
@@ -784,13 +784,13 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth
[[package]]
name = "fastapi"
version = "0.115.7"
version = "0.115.8"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false
python-versions = ">=3.8"
files = [
{file = "fastapi-0.115.7-py3-none-any.whl", hash = "sha256:eb6a8c8bf7f26009e8147111ff15b5177a0e19bb4a45bc3486ab14804539d21e"},
{file = "fastapi-0.115.7.tar.gz", hash = "sha256:0f106da6c01d88a6786b3248fb4d7a940d071f6f488488898ad5d354b25ed015"},
{file = "fastapi-0.115.8-py3-none-any.whl", hash = "sha256:753a96dd7e036b34eeef8babdfcfe3f28ff79648f86551eb36bfc1b0bf4a8cbf"},
{file = "fastapi-0.115.8.tar.gz", hash = "sha256:0ce9111231720190473e222cdf0f07f7206ad7e53ea02beb1d2dc36e2f0741e9"},
]
[package.dependencies]
@@ -1055,6 +1055,25 @@ python-dateutil = ">=2.8.1"
[package.extras]
dev = ["flake8", "markdown", "twine", "wheel"]
[[package]]
name = "gtts"
version = "2.5.4"
description = "gTTS (Google Text-to-Speech), a Python library and CLI tool to interface with Google Translate text-to-speech API"
optional = false
python-versions = ">=3.7"
files = [
{file = "gTTS-2.5.4-py3-none-any.whl", hash = "sha256:5dd579377f9f5546893bc26315ab1f846933dc27a054764b168f141065ca8436"},
{file = "gtts-2.5.4.tar.gz", hash = "sha256:f5737b585f6442f677dbe8773424fd50697c75bdf3e36443585e30a8d48c1884"},
]
[package.dependencies]
click = ">=7.1,<8.2"
requests = ">=2.27,<3"
[package.extras]
docs = ["sphinx", "sphinx-autobuild", "sphinx-click", "sphinx-mdinclude", "sphinx-rtd-theme"]
tests = ["pytest (>=7.1.3,<8.4.0)", "pytest-cov", "testfixtures"]
[[package]]
name = "h11"
version = "0.14.0"
@@ -1880,13 +1899,13 @@ pygments = ">2.12.0"
[[package]]
name = "mkdocs-material"
version = "9.6.2"
version = "9.6.4"
description = "Documentation that simply works"
optional = false
python-versions = ">=3.8"
files = [
{file = "mkdocs_material-9.6.2-py3-none-any.whl", hash = "sha256:71d90dbd63b393ad11a4d90151dfe3dcbfcd802c0f29ce80bebd9bbac6abc753"},
{file = "mkdocs_material-9.6.2.tar.gz", hash = "sha256:a3de1c5d4c745f10afa78b1a02f917b9dce0808fb206adc0f5bb48b58c1ca21f"},
{file = "mkdocs_material-9.6.4-py3-none-any.whl", hash = "sha256:414e8376551def6d644b8e6f77226022868532a792eb2c9accf52199009f568f"},
{file = "mkdocs_material-9.6.4.tar.gz", hash = "sha256:4d1d35e1c1d3e15294cb7fa5d02e0abaee70d408f75027dc7be6e30fb32e6867"},
]
[package.dependencies]
@@ -1920,23 +1939,22 @@ files = [
[[package]]
name = "mkdocstrings"
version = "0.27.0"
version = "0.28.1"
description = "Automatic documentation from sources, for MkDocs."
optional = false
python-versions = ">=3.9"
files = [
{file = "mkdocstrings-0.27.0-py3-none-any.whl", hash = "sha256:6ceaa7ea830770959b55a16203ac63da24badd71325b96af950e59fd37366332"},
{file = "mkdocstrings-0.27.0.tar.gz", hash = "sha256:16adca6d6b0a1f9e0c07ff0b02ced8e16f228a9d65a37c063ec4c14d7b76a657"},
{file = "mkdocstrings-0.28.1-py3-none-any.whl", hash = "sha256:a5878ae5cd1e26f491ff084c1f9ab995687d52d39a5c558e9b7023d0e4e0b740"},
{file = "mkdocstrings-0.28.1.tar.gz", hash = "sha256:fb64576906771b7701e8e962fd90073650ff689e95eb86e86751a66d65ab4489"},
]
[package.dependencies]
click = ">=7.0"
Jinja2 = ">=2.11.1"
Markdown = ">=3.6"
MarkupSafe = ">=1.1"
mkdocs = ">=1.4"
mkdocs-autorefs = ">=1.2"
platformdirs = ">=2.2"
mkdocs-autorefs = ">=1.3"
mkdocs-get-deps = ">=0.2"
pymdown-extensions = ">=6.3"
[package.extras]
@@ -4365,4 +4383,4 @@ propcache = ">=0.2.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "211d8b41dfd43afee62345619497bd7b6b64dad2b39ad2013c47beafd3f0a26b"
content-hash = "9f04c27a16a385191dc91ac21012ea2a48b54d9e4380bcaba72f3106979b4219"
+5 -4
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "agentic_security"
version = "0.4.4"
version = "0.4.5"
description = "Agentic LLM vulnerability scanner"
authors = ["Alexander Miasoiedov <msoedov@gmail.com>"]
maintainers = ["Alexander Miasoiedov <msoedov@gmail.com>"]
@@ -28,14 +28,14 @@ agentic_security = "agentic_security.__main__:main"
[tool.poetry.dependencies]
python = "^3.11"
fastapi = "^0.115.6"
fastapi = "^0.115.8"
uvicorn = "^0.34.0"
fire = "0.7.0"
loguru = "^0.7.3"
httpx = "^0.28.1"
cache-to-disk = "^2.0.0"
pandas = ">=1.4,<3.0"
datasets = ">=1.14,<4.0"
datasets = "^3.3.0"
tabulate = ">=0.8.9,<0.10.0"
colorama = "^0.4.4"
matplotlib = "^3.9.2"
@@ -47,6 +47,7 @@ jinja2 = "^3.1.4"
python-multipart = "^0.0.20"
tomli = "^2.2.1"
rich = "13.9.4"
gTTS = "^2.5.4"
# garak = { version = "*", optional = true }
@@ -66,7 +67,7 @@ huggingface-hub = ">=0.25.1,<0.29.0"
# Docs
mkdocs = ">=1.4.2"
mkdocs-material = ">=8.5.10"
mkdocs-material = "^9.6.4"
mkdocstrings = ">=0.26.1"
mkdocs-jupyter = ">=0.25.1"