Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
77310d2
fix: update default model IDs
ThomasCross Mar 30, 2026
a439f2c
Merge branch 'main' of https://github.com/ThomasCross/spikee
ThomasCross Mar 30, 2026
4d00f5c
feat: add digraphic language plugin
ThomasCross Mar 30, 2026
62a3a60
feat: Improve plugin module tag taxonomies and list representations
ThomasCross Mar 31, 2026
c9a7488
feat: Update attack module tags
ThomasCross Mar 31, 2026
1591a4a
docs: Add effectiveness notes for digraphic_translate plugin
ThomasCross Apr 2, 2026
d094aed
feat: Suppress warnings during model loading in OpusTranslator
ThomasCross Apr 2, 2026
87ffeff
dev: Suppress AnyLLM Bedrock provider async warnings
ThomasCross Apr 2, 2026
077a432
change: Enhance error handling in spikee list and add multi-modal tags
ThomasCross Apr 2, 2026
cc45898
feat: add text2image plugin
ThomasCross Apr 2, 2026
200f063
feat: add openai tts and stt providers
ThomasCross Apr 2, 2026
3b6837f
feat: add elevenlabs tts and stt providers
ThomasCross Apr 2, 2026
296d810
dev: update moduletags for TTS and STT providers
ThomasCross Apr 2, 2026
f0f824d
feat: add TTS plugin
ThomasCross Apr 2, 2026
58da7af
feat: add aws polly tts provider
ThomasCross Apr 2, 2026
59b90c8
dev: refactor LLMProvider
ThomasCross Apr 2, 2026
d9792fe
feat: implement streaming for TTS providers
ThomasCross Apr 2, 2026
2e9504e
feat: bedrock sso provider
ThomasCross Apr 10, 2026
31e3bd5
Merge branch 'tjc-multi-modal' of https://github.com/ThomasCross/spik…
ThomasCross Apr 10, 2026
3ee1805
change: update naming scheme and add docs
ThomasCross Apr 13, 2026
c838e81
feat: aws transcribe stt + linting + aws profiles to polly
ThomasCross Apr 13, 2026
193579e
change: move profiles to any-llm bedrock provider
ThomasCross Apr 14, 2026
fe31198
refactor: OpenAITTSProvider
ThomasCross Apr 16, 2026
778a51f
feat: add content wrapper to generator and plugins. Updated module de…
ThomasCross Apr 16, 2026
3c6119b
Merge branch 'main' of https://github.com/ReversecLabs/spikee into tj…
ThomasCross Apr 16, 2026
9359989
fix: generation content, update tests
ThomasCross Apr 16, 2026
1ff6dde
tests: add invalid content type test
ThomasCross Apr 16, 2026
2c3f763
feat: add content wrapper to tester
ThomasCross Apr 16, 2026
14b061c
refactor: update judge methods to use Text type and improve content h…
ThomasCross Apr 16, 2026
8d5c4a2
fix: provider hinting
ThomasCross Apr 16, 2026
df9cf03
change: fix type hinting and add content type checks for providers
ThomasCross Apr 16, 2026
fb0c0d6
change: minimised content wrappers
ThomasCross Apr 17, 2026
72e33ba
dev: add content wrapper tests and reduce duplicate tests
ThomasCross Apr 17, 2026
6b34cbf
feat: openai sts
ThomasCross Apr 17, 2026
205de49
refactor: google translate helper
ThomasCross Apr 17, 2026
8f3ffa6
docs: updated docs
ThomasCross Apr 17, 2026
4270875
fix: content wrapper generator bug
ThomasCross Apr 17, 2026
8924684
fix: async any-llm bug
ThomasCross Apr 17, 2026
67eab96
dev: update old default model in plugins
ThomasCross Apr 23, 2026
4c5aeb2
fix: handle plugin transformation errors and improve AWS credential h…
ThomasCross Apr 23, 2026
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
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ Spikee features several sample plugins and targets that require specific third-p

```bash
pip install "spikee[local-inference]"
pip install "spikee[google-translate]"
pip install "spikee[pdf]"
```


Expand Down
4 changes: 2 additions & 2 deletions docs/03_llm_providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Use `spikee list providers` to get a list of providers and known supported model
| OpenAI | `openai` | `gpt-4o` (default)<br/>`gpt-4.1` | `OPENAI_API_KEY` | [Models List](https://platform.openai.com/docs/models) |
| Azure OpenAI | `azure` | `gpt-4o` (default)<br/>`gpt-4o-mini` | `AZURE_OPENAI_API_KEY`<br/>`AZURE_OPENAI_ENDPOINT` | [Models List](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models) |
| AWS Bedrock | `bedrock` | `claude45-sonnet` (default)<br/>`claude45-haiku`<br/>`deepseek-v3`<br/><small>*(Allows internal shorthands)*</small> | `AWS_ACCESS_KEY_ID`<br/>`AWS_SECRET_ACCESS_KEY`<br/>`AWS_DEFAULT_REGION` | [Models List](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) |
| Google Gemini | `google` | `gemini-2.5-flash` (default)<br/>`gemini-2.5-pro`<br/>`gemini-3-pro` | `GEMINI_API_KEY` | [Models List](https://ai.google.dev/gemini-api/docs/models/gemini) |
| Google Gemini | `google` | `gemini-2.5-flash` (default)<br/>`gemini-2.5-pro`<br/>`gemini-3-pro` | `GOOGLE_API_KEY` | [Models List](https://ai.google.dev/gemini-api/docs/models/gemini) |
| Deepseek | `deepseek` | `deepseek-chat` (default)<br/>`deepseek-reasoner` | `DEEPSEEK_API_KEY` | [Models List](https://platform.deepseek.com/api-docs/) |
| Groq | `groq` | `llama-3.1-8b-instant` (default)<br/>`llama-3.3-70b-versatile` | `GROQ_API_KEY` | [Models List](https://console.groq.com/docs/models) |
| TogetherAI | `together` | `gemma2-8b` (default)<br/>`mixtral-8x22b`<br/><small>*(Allows internal shorthands)*</small> | `TOGETHER_API_KEY` | [Models List](https://docs.together.ai/docs/inference-models) |
Expand Down Expand Up @@ -183,7 +183,7 @@ class ExampleProvider(Provider):

self.llm = ...

def get_description(self) -> Tuple[List[ModuleTag], str]:
def get_description(self) -> ModuleDescriptionHint:
return [ModuleTag.LLM], "Sample LLM Provider, always returns 'Hello, world!'"

def invoke(self, messages: Union[str, List[Union[Message, dict, tuple, str]]]) -> AIMessage:
Expand Down
3 changes: 3 additions & 0 deletions docs/04_dataset_generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ Spikee supports two types of multi-turn datasets:

# Transformations

> **Dataset Entry Format Note:**
> Seed files use a `"text"` field for input content. The output JSONL datasets produced by `spikee generate` serialize each entry using `"content"` + `"content_type"` fields instead of `"text"`. Legacy datasets with only a `"text"` field are still accepted by `spikee test` for backward compatibility. When writing tooling that reads generated datasets, use the `"content"` field (and check `"content_type"` for multimodal entries).

### Plugins `--plugins`
Plugins are Python script that transforms a payload during dataset generation. This is typically used to assess transformation based jailbreaking techniques, or to modify prompts into a target friendly format.

Expand Down
70 changes: 38 additions & 32 deletions docs/06_custom_targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,35 @@ Every target is a Python module located in the `targets/` directory of your work
### Target Template
```python
from spikee.templates.target import Target
from spikee.tester.guardrail_trigger import GuardrailTrigger
from spikee.tester import GuardrailTrigger, RetryableError
from spikee.utilities.enums import ModuleTag
from spikee.utilities.hinting import Content, TargetResponseHint, ModuleDescriptionHint, ModuleOptionsHint
from typing import Optional, Dict, List, Tuple, Union, Any
import requests

class ExampleTarget(Target):
def get_description(self) -> Tuple[List[ModuleTag], str]:
def get_description(self) -> ModuleDescriptionHint:
return [ModuleTag.SINGLE], "Example Target Template"

def get_available_option_values(self) -> Tuple[List[str], bool]:
def get_available_option_values(self) -> ModuleOptionsHint:
"""Return supported attack options; Tuple[options (default is first), llm_required]"""
return [], False

def process_input(
self,
input_text: str,
system_message: Optional[str] = None,
input_text: Content,
system_message: Optional[Content] = None,
target_options: Optional[str] = None,
) -> Union[str, bool, Tuple[Union[str, bool], Any]]:
) -> TargetResponseHint:
"""Sends prompts to the defined target

Args:
input_text (str): User Prompt
system_message (Optional[str], optional): System Prompt. Defaults to None.
input_text (Content): User Prompt
system_message (Optional[Content], optional): System Prompt. Defaults to None.
target_options (Optional[str], optional): Target options. Defaults to None.

Returns:
str | Tuple[str, Any] | bool: Response from the target (text response | guardrail result | boolean for guardrail)
Content | bool | Tuple[Content | bool, Any]: Response from the target (text response | guardrail result | boolean for guardrail)

throws tester.GuardrailTrigger: Indicates guardrail was triggered
throws Exception: Raises exception on failure
Expand Down Expand Up @@ -77,10 +78,10 @@ if __name__ == "__main__":
This is the core function that Spikee calls for every test case - it receives a dataset entry and returns the target's response.

#### Parameters
* `input_text: str`:
The user prompt / dataset entry generated by Spikee. When testing an application, this is typically the data you are submitting (e.g., the body of an email, a user comment, a document for summarization).
* `input_text: Content`:
The user prompt / dataset entry generated by Spikee. For text-based targets this is a plain string. Multimodal targets may receive an `Audio` or `Image` object — use `get_content(input_text)` from `spikee.utilities.hinting` to extract the raw value if needed.

* `system_message: Optional[str]`:
* `system_message: Optional[Content]`:
The system prompt, if specified in the dataset. **When testing an application, you will likely ignore this parameter**, as you typically cannot control the application's internal system prompt. It is mainly used when testing a standalone LLM.

* `target_options: Optional[str]`:
Expand All @@ -100,25 +101,27 @@ To make your target more flexible, you can advertise its supported `target_optio
```python
# Basic Implementation
from typing import List, Tuple, Union, Any
from spikee.utilities.hinting import Content, TargetResponseHint, ModuleOptionsHint
from spikee.utilities.modules import parse_options # Utility function to parse target_options string into a dictionary

def get_available_option_values(self) -> Tuple[List[str], bool]:
def get_available_option_values(self) -> ModuleOptionsHint:
"""Return supported attack options; Tuple[options (default is first), llm_required]"""
return ["mode=default_option", "additional_option1", "additional_option2"], False

def process_input(
self,
input_text: str,
system_message: Optional[str] = None,
input_text: Content,
system_message: Optional[Content] = None,
target_options: Optional[str] = None,
) -> Union[str, bool, Tuple[Union[str, bool], Any]]:
) -> TargetResponseHint:
options = parse_options(target_options)
mode = options.get("mode", "default_option")
```

```python
# Basic Implementation
from typing import List, Tuple, Union, Any, Dict
from typing import List, Tuple, Union, Any, Dict, Optional
from spikee.utilities.hinting import Content, TargetResponseHint, ModuleOptionsHint
from spikee.utilities.modules import parse_options # Utility function to parse target_options string into a dictionary

_OPTIONS_MAP: Dict[str, str] = {
Expand All @@ -127,18 +130,18 @@ _OPTIONS_MAP: Dict[str, str] = {
}
_DEFAULT_KEY = "example1"

def get_available_option_values(self) -> Tuple[List[str], bool]:
def get_available_option_values(self) -> ModuleOptionsHint:
"""Return supported attack options; Tuple[options (default is first), llm_required]"""
options = ["mode=" + self._DEFAULT_KEY]
options.extend([key for key in self._OPTIONS_MAP if key != self._DEFAULT_KEY])
return options, False

def process_input(
self,
input_text: str,
system_message: Optional[str] = None,
input_text: Content,
system_message: Optional[Content] = None,
target_options: Optional[str] = None,
) -> Union[str, bool, Tuple[Union[str, bool], Any]]:
) -> TargetResponseHint:
options = parse_options(target_options)
mode = options.get("mode", "default_option")

Expand All @@ -157,10 +160,11 @@ When this function is present, `spikee list targets` will display the available
* **API Calls:** Wrap all external API calls in a `try...except` block. If an exception occurs, log it and **re-raise the exception**. This allows Spikee's main testing loop to catch the error and apply its retry logic (`--max-retries`).
* **Custom Errors:** Use built-in Spikee exceptions from `spikee.tester` for the following cases:
* **Guardrail Triggers:** Guardrail is triggered, **raise a `GuardrailTrigger(msg, categories: Dict[str, Any])` exception**. This informs Spikee that the payload was blocked, allowing it to log the result correctly.
* **Rate Limiting / Throttling:** If the target returns a 429 or similar transient error, **raise a `RetryableError(msg, retry_period=60)` exception**. Spikee will back off and retry automatically, respecting the `retry_period` in seconds.

```python
# Guardrail Trigger Example
from spikee.tester.guardrail_trigger import GuardrailTrigger
from spikee.tester import GuardrailTrigger, RetryableError
import requests

try:
Expand Down Expand Up @@ -260,6 +264,7 @@ from typing import List, Tuple, Union, Any, Optional

from spikee.templates.multi_target import MultiTarget
from spikee.utilities.enums import Turn, ModuleTag
from spikee.utilities.hinting import Content, TargetResponseHint, ModuleDescriptionHint, ModuleOptionsHint


class SampleMultiTurnTarget(MultiTarget):
Expand All @@ -272,21 +277,21 @@ class SampleMultiTurnTarget(MultiTarget):
backtrack=True
)

def get_description(self) -> Tuple[List[ModuleTag], str]:
def get_description(self) -> ModuleDescriptionHint:
return [ModuleTag.MULTI], "Example Multi-Turn Target Template"

def get_available_option_values(self) -> Tuple[List[str], bool]:
def get_available_option_values(self) -> ModuleOptionsHint:
"""Return supported attack options; Tuple[options (default is first), llm_required]"""
return [], False

def process_input(
self,
input_text: str,
system_message: Optional[str] = None,
input_text: Content,
system_message: Optional[Content] = None,
target_options: Optional[str] = None,
spikee_session_id: Optional[str] = None,
backtrack: Optional[bool] = False,
) -> Union[str, bool, Tuple[Union[str, bool], Any]]:
) -> TargetResponseHint:
# Handle single-turn interactions, assign a random UUIDv4
if spikee_session_id is None:
spikee_session_id = "single_turn_" + str(uuid.uuid4())
Expand Down Expand Up @@ -326,6 +331,7 @@ from typing import List, Tuple, Union, Any, Optional

from spikee.templates.simple_multi_target import SimpleMultiTarget
from spikee.utilities.enums import Turn, ModuleTag
from spikee.utilities.hinting import Content, TargetResponseHint, ModuleDescriptionHint, ModuleOptionsHint


class SampleSimpleMultiTurnTarget(SimpleMultiTarget):
Expand All @@ -335,21 +341,21 @@ class SampleSimpleMultiTurnTarget(SimpleMultiTarget):
backtrack=True
)

def get_description(self) -> Tuple[List[ModuleTag], str]:
def get_description(self) -> ModuleDescriptionHint:
return [ModuleTag.MULTI], "Example Simple Multi-Turn Target Template"

def get_available_option_values(self) -> Tuple[List[str], bool]:
def get_available_option_values(self) -> ModuleOptionsHint:
"""Return supported attack options; Tuple[options (default is first), llm_required]"""
return [], False

def process_input(
self,
input_text: str,
system_message: Optional[str] = None,
input_text: Content,
system_message: Optional[Content] = None,
target_options: Optional[str] = None,
spikee_session_id: Optional[str] = None,
backtrack: Optional[bool] = False,
) -> Union[str, bool, Tuple[Union[str, bool], Any]]:
) -> TargetResponseHint:
target_session_id = None
if spikee_session_id is None:
# Handle single-turn interactions, assign a random UUIDv4
Expand Down
Loading
Loading