🐙 Mocktopus
Multi-armed mocks for LLM apps
Mocktopus is a drop-in replacement for OpenAI/Anthropic APIs, designed to make your LLM application tests fast, deterministic, and cost-free.
Why Mocktopus?
Testing LLM applications is challenging:
- Non-deterministic: Same prompt, different responses
- Expensive: Every test run costs API credits
- Slow: API calls add latency to test suites
- Network-dependent: Can't run tests offline
- Complex workflows: Tool calls and streaming complicate testing
Mocktopus solves these problems by providing a local mock server that perfectly mimics LLM APIs.
Features
✅ Drop-in replacement - Just change your base URL ✅ Deterministic responses - Same input → same output ✅ Tool/function calling - Full support for complex workflows ✅ Streaming - Server-sent events (SSE) support ✅ Multiple providers - OpenAI and Anthropic compatible ✅ Zero cost - No API charges for tests ✅ Fast - No network latency ✅ Offline - Run tests without internet
Installation
pip install mocktopus
Quick Start
1. Create a scenario file (scenario.yaml):
version: 1
rules:
- type: llm.openai
when:
model: "gpt-4*"
messages_contains: "hello"
respond:
content: "Hello! How can I help you today?"
2. Start the mock server:
mocktopus serve -s scenario.yaml
3. Point your app to Mocktopus:
from openai import OpenAI
# Instead of the real API:
# client = OpenAI(api_key="sk-...")
# Use Mocktopus:
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="mock-key" # Any string works
)
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "hello"}]
)
print(response.choices[0].message.content)
# Output: "Hello! How can I help you today?"
Usage Modes
Mock Mode (Default)
Use predefined YAML scenarios for deterministic responses:
mocktopus serve -s examples/chat-basic.yaml
Record Mode (Coming Soon)
Proxy and record real API calls for later replay:
mocktopus serve --mode record --recordings-dir ./recordings
Replay Mode (Coming Soon)
Replay previously recorded API interactions:
mocktopus serve --mode replay --recordings-dir ./recordings
Scenario Examples
Basic Chat Response
version: 1
rules:
- type: llm.openai
when:
messages_contains: "weather"
respond:
content: "It's sunny today!"
Function Calling
version: 1
rules:
- type: llm.openai
when:
messages_contains: "weather"
respond:
tool_calls:
- id: "call_123"
type: "function"
function:
name: "get_weather"
arguments: '{"location": "San Francisco"}'
Streaming Response
version: 1
rules:
- type: llm.openai
when:
model: "*"
respond:
content: "This will be streamed..."
delay_ms: 50 # Delay between chunks
chunk_size: 5 # Characters per chunk
Limited Usage
version: 1
rules:
- type: llm.openai
when:
messages_contains: "test"
times: 3 # Only responds 3 times
respond:
content: "Limited response"
CLI Commands
Start Server
# Basic usage
mocktopus serve -s scenario.yaml
# Custom port
mocktopus serve -s scenario.yaml -p 9000
# Verbose logging
mocktopus serve -s scenario.yaml -v
Test Scenarios
# Validate a scenario file
mocktopus validate scenario.yaml
# Simulate a request without starting server
mocktopus simulate -s scenario.yaml --prompt "Hello"
# Generate example scenarios
mocktopus example --type basic > my-scenario.yaml
mocktopus example --type tools > tools-scenario.yaml
Testing with Mocktopus
Pytest Integration
import pytest
from mocktopus import use_mocktopus
def test_my_llm_app(use_mocktopus):
# Load scenario
use_mocktopus.load_yaml("tests/scenarios/test.yaml")
# Get a client
client = use_mocktopus.openai_client()
# Test your app
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "test"}]
)
assert "expected" in response.choices[0].message.content
Continuous Integration
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- run: pip install -e .
- run: mocktopus serve -s tests/scenarios.yaml &
- run: pytest # Your tests hit localhost:8080
Advanced Features
Pattern Matching
Mocktopus supports multiple matching strategies:
- Exact match:
messages_contains: "exact phrase" - Regex:
messages_regex: "\\d+ items?" - Glob:
model: "gpt-4*"
Response Configuration
respond:
content: "Response text"
delay_ms: 100 # Simulate latency
usage:
input_tokens: 10
output_tokens: 20
# For streaming
chunk_size: 10 # Characters per chunk
Roadmap
- OpenAI chat completions API
- Streaming support (SSE)
- Function/tool calling
- Anthropic messages API
- Recording & replay
- Embeddings API
- Assistants API
- Image generation
- Semantic similarity matching
- Response templating
- Load testing mode
Contributing
We welcome contributions! See our Contributing Guide for details.
License
MIT - See LICENSE for details.
Links
Made with 🐙 by EvalOps
Metadata
Release files for mocktopus 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mocktopus-0.2.0.tar.gz | 37.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mocktopus-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.0 kB
Release files / mocktopus-0.2.0.tar.gz
| Download URL | mocktopus-0.2.0.tar.gz |
|---|---|
| Size | 37.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1887a87cce2a46819ec2ed915cbf1f8f6f52a62326da1387fdf467cc9316b379
|
|
BLAKE2b-256 checksum How to use checksums |
b891de138d113ec5a933e747147d220ac012b891cd6f9d5b887e1194f708c599
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / mocktopus-0.2.0-py3-none-any.whl
| Download URL | mocktopus-0.2.0-py3-none-any.whl |
|---|---|
| Size | 33.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
77e5660e388ef5b895afa76122c1315d183a0f8cb045cf720ae446562c0bdfa0
|
|
BLAKE2b-256 checksum How to use checksums |
f8bdfd2504adec48546c0ce778b57f3e5ddc2eea79f904b9c5f0f6ff3f501ccf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|