Initial commit: SpongeBob vocabulary transformer plugin
- Random opening interjections (25% chance, configurable)- Pattern-based vocabulary replacement (Wow! → Tartar sauce!) - Preserves code blocks, URLs, file paths - Zero-token post-processing via transform_llm_output hook
This commit is contained in:
parent
8c6775bffb
commit
d97e28467d
3 changed files with 251 additions and 1 deletions
79
README.md
79
README.md
|
|
@ -1,3 +1,80 @@
|
|||
# spongebob-vocab
|
||||
|
||||
SpongeBob vocabulary transformer plugin for Hermes Agent - zero-token personality injection via transform_llm_output hook
|
||||
SpongeBob vocabulary transformer plugin for Hermes Agent. AddsBarnacleBoy personality through zero-token `transform_llm_output` hooks.
|
||||
|
||||
## What it does
|
||||
|
||||
1. **Random opening interjections** - 25% chance to prepend phrases like "Jumping jellyfish!" or "Tartar sauce!" at the start of responses
|
||||
2. **Pattern-based vocabulary replacement** - Transforms words like "Wow!" → "Tartar sauce!", "Amazing!" → "Holy Krabby Patties!"
|
||||
3. **Preserves technical content** - Code blocks, URLs, file paths, and shell commands are never modified
|
||||
|
||||
## Installation
|
||||
|
||||
Copy to your Hermes plugins directory:
|
||||
|
||||
```bash
|
||||
cp -r spongebob-vocab ~/.hermes/plugins/
|
||||
```
|
||||
|
||||
## Activation
|
||||
|
||||
Set the environment variable:
|
||||
|
||||
```bash
|
||||
export SPONGEBOB_MODE=on
|
||||
```
|
||||
|
||||
Or add to your shell config:
|
||||
|
||||
```bash
|
||||
echo 'export SPONGEBOB_MODE=on' >> ~/.bashrc
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `SPONGEBOB_MODE` | `off` | Set to `on`, `1`, `true`, or `yes` to enable |
|
||||
| `SPONGEBOB_INTERJECTION_CHANCE` | `0.25` | Probability (0.0-1.0) of adding opening interjection |
|
||||
|
||||
## Opening Interjections
|
||||
|
||||
Randomly selected from:
|
||||
|
||||
- Jumping jellyfish!
|
||||
- Tartar sauce!
|
||||
- Barnacles!
|
||||
- Holy Krabby Patties!
|
||||
- Great Neptune's nostrils!
|
||||
- Mother of Pearl!
|
||||
- Flappin' flounders!
|
||||
- Holy fish paste!
|
||||
- Holy shrimp!
|
||||
- Great Barrier Reef!
|
||||
- Aw, fish paste!
|
||||
- Holy cephalopod!
|
||||
- What the barnacle!
|
||||
|
||||
## Vocabulary Patterns
|
||||
|
||||
| Original | SpongeBob |
|
||||
|----------|-----------|
|
||||
| Wow! | Tartar sauce! |
|
||||
| Amazing! | Holy Krabby Patties! |
|
||||
| Excellent! | Holy fish paste! |
|
||||
| Perfect! | Holy cephalopod! |
|
||||
| Fantastic! | Holy shrimp! |
|
||||
| Brilliant! | Great Barrier Reef! |
|
||||
| Damn! | Barnacles! |
|
||||
| Ugh! | Fish paste! |
|
||||
|
||||
## Technical Details
|
||||
|
||||
- Uses `transform_llm_output` hook - runs after LLM generation
|
||||
- Zero additional inference tokens (post-processing only)
|
||||
- Preserves code blocks, inline code, URLs, file paths, shell commands
|
||||
- Anti-double-interjection: won't add if response already starts with an interjection
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
167
__init__.py
Normal file
167
__init__.py
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
"""
|
||||
SpongeBob vocabulary transformer for BarnacleBoy.
|
||||
|
||||
Two modes:
|
||||
1. Pattern-based vocabulary replacement (Wow! → Tartar sauce!)
|
||||
2. Random opening interjections (Jumping jellyfish! Let's...)
|
||||
|
||||
Hook: transform_llm_output
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
import random
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Opening interjections - randomly prepended to responses
|
||||
# These are BarnacleBoy's signature exclamations
|
||||
OPENING_INTERJECTIONS = [
|
||||
"Jumping jellyfish!",
|
||||
"Tartar sauce!",
|
||||
"Barnacles!",
|
||||
"Holy Krabby Patties!",
|
||||
"Great Neptune's nostrils!",
|
||||
"Mother of Pearl!",
|
||||
"Flappin' flounders!",
|
||||
"Holy fish paste!",
|
||||
"Holy shrimp!",
|
||||
"Great Barrier Reef!",
|
||||
"Aw, fishpaste!",
|
||||
"Holy cephalopod!",
|
||||
"What the barnacle!",
|
||||
]
|
||||
|
||||
# Vocabulary replacements - case-insensitive regex patterns
|
||||
# Format: (pattern, replacement)
|
||||
VOCABULARY_PATTERNS = [
|
||||
# Exclamations (surprise, excitement) - standalone or at start
|
||||
(r'\bWow!\s', 'Tartar sauce! '),
|
||||
(r'\bWow!\Z', 'Tartar sauce!'),
|
||||
(r'\bWow,', 'Tartar sauce,'),
|
||||
|
||||
# Amazing variations
|
||||
(r'\b[Aa]mazing!\s', 'Holy Krabby Patties! '),
|
||||
(r'\b[Aa]mazing!\Z', 'Holy Krabby Patties!'),
|
||||
|
||||
# Excellent
|
||||
(r'\b[Ee]xcellent!\s', 'Holy fish paste! '),
|
||||
(r'\b[Ee]xcellent!\Z', 'Holy fish paste!'),
|
||||
|
||||
# Great
|
||||
(r'\bGreat!\s', 'Barnacles! '),
|
||||
(r'\bGreat!\Z', 'Barnacles!'),
|
||||
|
||||
# Perfect
|
||||
(r'\b[Pp]erfect!\s', 'Holy cephalopod! '),
|
||||
(r'\b[Pp]erfect!\Z', 'Holy cephalopod!'),
|
||||
|
||||
# Fantastic
|
||||
(r'\b[Ff]antastic!\s', 'Holy shrimp! '),
|
||||
(r'\b[Ff]antastic!\Z', 'Holy shrimp!'),
|
||||
|
||||
# Brilliant
|
||||
(r'\bBrilliant!', 'Great Barrier Reef!'),
|
||||
|
||||
# Damn frustration
|
||||
(r'\b[Dd]amn!', 'Barnacles!'),
|
||||
(r'\b[Dd]amn,', 'Aw, barnacles,'),
|
||||
|
||||
# Ugh frustration
|
||||
(r'\bUgh!', 'Fish paste!'),
|
||||
(r'\bUgh,', 'Aw, fish paste!'),
|
||||
|
||||
# Fantastic praise
|
||||
(r'\b[Ff]antastic!', 'Mother of Pearl!'),
|
||||
|
||||
# Common openers
|
||||
(r'\bWell,', "Flappin' flounders,"),
|
||||
(r'\bOh,', 'Oh, barnacles,'),
|
||||
]
|
||||
|
||||
# Patterns to preserve (never transform)
|
||||
PRESERVE_PATTERNS = [
|
||||
r'```[\s\S]*?```', # Code blocks
|
||||
r'`[^`]+`', # Inline code
|
||||
r'https?://[^\s]+', # URLs
|
||||
r'~/[^\s]+', # File paths starting with ~
|
||||
r'/[a-zA-Z][^\s]*', # Absolute paths (start with /)
|
||||
r'\$[^\n]+', # Shell commands
|
||||
]
|
||||
|
||||
|
||||
def transform_vocabulary(response_text: str, session_id: str = "", model: str = "", platform: str = "") -> str:
|
||||
"""
|
||||
Transform response text with SpongeBob vocabulary.
|
||||
|
||||
Args:
|
||||
response_text: The LLM's output text
|
||||
session_id: Session identifier (for context-aware decisions)
|
||||
model: Model name (unused but required by hook signature)
|
||||
platform: Platform name (e.g., "discord", "telegram")
|
||||
|
||||
Returns:
|
||||
Transformed text with SpongeBob vocabulary, or None if disabled.
|
||||
Non-None non-empty string takes precedence over other hooks.
|
||||
"""
|
||||
# Check if SpongeBob mode is enabled
|
||||
mode = os.environ.get("SPONGEBOB_MODE", "").lower()
|
||||
if mode not in ("on", "1", "true", "yes"):
|
||||
return None # Not enabled, let other hooks or default pass through
|
||||
|
||||
if not response_text or not response_text.strip():
|
||||
return None # Empty response, nothing to transform
|
||||
|
||||
logger.info("[spongebob-vocab] Hook fired, transforming output")
|
||||
|
||||
# Find all regions to preserve
|
||||
preserved = []
|
||||
preserved_text = response_text
|
||||
|
||||
for pattern in PRESERVE_PATTERNS:
|
||||
for match in re.finditer(pattern, response_text, re.MULTILINE):
|
||||
placeholder = f"\x00PRESERVE{len(preserved)}\x00"
|
||||
preserved_text = preserved_text.replace(match.group(0), placeholder)
|
||||
preserved.append(match.group(0))
|
||||
|
||||
# Apply vocabulary transformations
|
||||
transformed = preserved_text
|
||||
for pattern, replacement in VOCABULARY_PATTERNS:
|
||||
transformed = re.sub(pattern, replacement, transformed)
|
||||
|
||||
# Restore preserved regions
|
||||
for i, original in enumerate(preserved):
|
||||
transformed = transformed.replace(f"\x00PRESERVE{i}\x00", original)
|
||||
|
||||
# Add random opening interjection (25% chance)
|
||||
# Configurable via SPONGEBOB_INTERJECTION_CHANCE env var(0.0-1.0)
|
||||
interjection_chance = float(os.environ.get("SPONGEBOB_INTERJECTION_CHANCE", "0.25"))
|
||||
|
||||
if random.random() < interjection_chance:
|
||||
# Pick a random interjection
|
||||
interjection = random.choice(OPENING_INTERJECTIONS)
|
||||
|
||||
# Check if response already starts with an interjection-like pattern
|
||||
# (avoid double-interjecting if the LLM already started with one)
|
||||
first_line = transformed.split('\n')[0].strip()
|
||||
already_interjected = any(
|
||||
first_line.startswith(exc.rstrip('!')) or first_line.startswith(exc)
|
||||
for exc in OPENING_INTERJECTIONS[:6] # Check common ones
|
||||
)
|
||||
|
||||
if not already_interjected:
|
||||
# Prepend interjection with newline separator
|
||||
transformed = f"{interjection} {transformed}"
|
||||
logger.info(f"[spongebob-vocab] Prepended interjection: {interjection}")
|
||||
|
||||
return transformed
|
||||
|
||||
|
||||
def register(ctx):
|
||||
"""Register the transform hook with Hermes."""
|
||||
ctx.register_hook("transform_llm_output", transform_vocabulary)
|
||||
logger.info("[spongebob-vocab] Registered transform_llm_output hook")
|
||||
|
||||
|
||||
__all__ = ["transform_vocabulary", "register"]
|
||||
6
plugin.yaml
Normal file
6
plugin.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
name: spongebob-vocab
|
||||
version: 1.0.0
|
||||
description: SpongeBob vocabulary transformation via transform_llm_output hook (zero-token personality injection)
|
||||
author: BarnacleBoy
|
||||
hooks:
|
||||
transform_llm_output: transform_vocabulary
|
||||
Loading…
Add table
Add a link
Reference in a new issue