0d3cb498a3
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Waiting to run
Test and Publish Multi-arch Docker Image / test (push) Waiting to run
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Blocked by required conditions
Validate Renovate Config / Validate Renovate Configuration (push) Waiting to run
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
377 lines
7.9 KiB
Markdown
377 lines
7.9 KiB
Markdown
# redteam-tracing-example (Red Team Tracing)
|
|
|
|
You can run this example with:
|
|
|
|
```bash
|
|
npx promptfoo@latest init --example redteam-tracing-example
|
|
cd redteam-tracing-example
|
|
```
|
|
|
|
This example demonstrates how to use tracing with red team strategies to provide attackers and graders with visibility into the internal operations of your LLM application.
|
|
|
|
## Quick Start
|
|
|
|
**1. Install dependencies:**
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
**2. Start the mock traced server:**
|
|
|
|
```bash
|
|
npm run server
|
|
```
|
|
|
|
This starts an HTTP server on port 3110 that:
|
|
|
|
- Accepts chat requests
|
|
- Generates OTLP trace spans (LLM calls, guardrails, tools)
|
|
- Sends spans to promptfoo's OTLP receiver
|
|
|
|
**3. Test the server (optional):**
|
|
|
|
```bash
|
|
# In another terminal
|
|
./test-server.sh
|
|
```
|
|
|
|
**4. Run the red team evaluation:**
|
|
|
|
```bash
|
|
# In another terminal (from the project root)
|
|
npm run local -- eval -c examples/redteam-tracing-example/promptfooconfig.yaml
|
|
```
|
|
|
|
**5. View the results:**
|
|
|
|
```bash
|
|
npm run local -- view
|
|
```
|
|
|
|
You'll see trace data in:
|
|
|
|
- Attack prompts (when `includeInAttack: true`)
|
|
- Grading context (when `includeInGrading: true`)
|
|
- Test metadata (`traceSnapshots`)
|
|
|
|
## Troubleshooting
|
|
|
|
**Server not responding?**
|
|
|
|
```bash
|
|
# Check if server is running
|
|
curl http://localhost:3110/health
|
|
|
|
# Test basic request
|
|
curl -X POST http://localhost:3110/chat \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"prompt": "test"}'
|
|
```
|
|
|
|
**No traces appearing?**
|
|
|
|
- Make sure the server is emitting to the correct OTLP endpoint (check server logs)
|
|
- Verify promptfoo's OTLP receiver is enabled in config (`tracing.enabled: true`)
|
|
- Check that `traceparent` headers are being passed (set in provider context)
|
|
|
|
## What is Red Team Tracing?
|
|
|
|
Red team tracing allows adversarial strategies to see what happens inside your LLM application during an attack, including:
|
|
|
|
- Tool calls and their results
|
|
- Guardrail decisions
|
|
- Internal LLM calls
|
|
- Error conditions
|
|
- Performance metrics
|
|
|
|
This information can help:
|
|
|
|
1. **Attack generation**: Craft more effective attacks by understanding how the system responds internally
|
|
2. **Grading**: Make more informed decisions about whether an attack succeeded by seeing internal behavior
|
|
|
|
## Configuration
|
|
|
|
### Basic Configuration
|
|
|
|
Enable tracing in your `promptfooconfig.yaml`:
|
|
|
|
```yaml
|
|
redteam:
|
|
tracing:
|
|
# Enable tracing for all strategies
|
|
enabled: true
|
|
|
|
# Include trace data in attack generation (default: true)
|
|
includeInAttack: true
|
|
|
|
# Include trace data in grading (default: true)
|
|
includeInGrading: true
|
|
|
|
plugins:
|
|
- harmful
|
|
- pii
|
|
|
|
strategies:
|
|
- crescendo
|
|
- goat
|
|
```
|
|
|
|
### Advanced Configuration
|
|
|
|
Configure tracing behavior:
|
|
|
|
```yaml
|
|
redteam:
|
|
tracing:
|
|
enabled: true
|
|
|
|
# Include internal spans (e.g., tokenization, parsing)
|
|
includeInternalSpans: false
|
|
|
|
# Maximum number of spans to fetch per iteration
|
|
maxSpans: 50
|
|
|
|
# Maximum depth of nested spans to fetch
|
|
maxDepth: 5
|
|
|
|
# Retry configuration for fetching traces
|
|
maxRetries: 3
|
|
retryDelayMs: 500
|
|
|
|
# Filter spans by name pattern (optional)
|
|
spanFilter:
|
|
- 'llm.*'
|
|
- 'tool.*'
|
|
- 'guardrail.*'
|
|
|
|
# Sanitize sensitive attributes (recommended)
|
|
sanitizeAttributes: true
|
|
```
|
|
|
|
### Strategy-Specific Configuration
|
|
|
|
Different strategies may need different tracing settings:
|
|
|
|
```yaml
|
|
redteam:
|
|
tracing:
|
|
enabled: true
|
|
|
|
# Strategy-specific overrides
|
|
strategies:
|
|
# Crescendo benefits from seeing guardrail decisions
|
|
crescendo:
|
|
includeInAttack: true
|
|
includeInGrading: true
|
|
spanFilter:
|
|
- 'guardrail.*'
|
|
- 'llm.*'
|
|
|
|
# GOAT can use tool call information
|
|
goat:
|
|
includeInAttack: true
|
|
spanFilter:
|
|
- 'tool.*'
|
|
- 'llm.*'
|
|
|
|
# Iterative may want full trace data
|
|
iterative:
|
|
includeInAttack: true
|
|
includeInGrading: true
|
|
maxSpans: 100
|
|
```
|
|
|
|
### Test-Level Configuration
|
|
|
|
Override tracing for specific tests:
|
|
|
|
```yaml
|
|
tests:
|
|
- description: 'Test with custom tracing'
|
|
vars:
|
|
query: 'Tell me about sensitive data'
|
|
metadata:
|
|
tracing:
|
|
enabled: true
|
|
includeInAttack: true
|
|
includeInGrading: true
|
|
maxSpans: 200
|
|
```
|
|
|
|
## How Tracing Works
|
|
|
|
### 1. Attack Generation
|
|
|
|
When `includeInAttack: true`, the attacker receives a trace summary like:
|
|
|
|
```text
|
|
Trace 0af76519 • 5 spans
|
|
|
|
Execution Flow:
|
|
1. [1.2s] llm.generate (client) | model=gpt-4
|
|
2. [300ms] guardrail.check (internal) | tool=content-filter
|
|
3. [150ms] tool.database_query (server) | tool=search
|
|
4. [50ms] guardrail.check (internal) | ERROR: Rate limit exceeded
|
|
5. [800ms] llm.generate (client) | model=gpt-4
|
|
|
|
Key Observations:
|
|
• Guardrail content-filter decision: blocked
|
|
• Tool call search via "tool.database_query" (duration 150ms)
|
|
• Error span "guardrail.check" (span-4): Rate limit exceeded
|
|
```
|
|
|
|
The attacker can use this information to craft better attacks (e.g., targeting the rate limit error).
|
|
|
|
### 2. Grading
|
|
|
|
When `includeInGrading: true`, graders receive the same trace context and can make more informed decisions:
|
|
|
|
```typescript
|
|
// Grader receives:
|
|
{
|
|
prompt: "...",
|
|
llmOutput: "...",
|
|
test: {...},
|
|
gradingContext: {
|
|
traceContext: {
|
|
traceId: "...",
|
|
spans: [...],
|
|
insights: [...]
|
|
},
|
|
traceSummary: "..."
|
|
}
|
|
}
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Start with Default Settings
|
|
|
|
The default configuration works well for most use cases:
|
|
|
|
```yaml
|
|
redteam:
|
|
tracing:
|
|
enabled: true
|
|
```
|
|
|
|
### 2. Use spanFilter for Focused Analysis
|
|
|
|
If you only care about specific operations:
|
|
|
|
```yaml
|
|
redteam:
|
|
tracing:
|
|
enabled: true
|
|
spanFilter:
|
|
- 'guardrail.*' # Only guardrail spans
|
|
- 'tool.*' # Only tool calls
|
|
```
|
|
|
|
### 3. Keep sanitizeAttributes Enabled
|
|
|
|
Always sanitize attributes in production:
|
|
|
|
```yaml
|
|
redteam:
|
|
tracing:
|
|
enabled: true
|
|
sanitizeAttributes: true # Recommended
|
|
```
|
|
|
|
### 4. Adjust maxSpans Based on Complexity
|
|
|
|
- Simple apps: `maxSpans: 20`
|
|
- Medium complexity: `maxSpans: 50` (default)
|
|
- Complex agentic systems: `maxSpans: 100-200`
|
|
|
|
### 5. Use Strategy-Specific Overrides
|
|
|
|
Different strategies benefit from different trace data:
|
|
|
|
- **Crescendo**: Needs guardrail information
|
|
- **GOAT**: Benefits from tool call traces
|
|
- **Iterative**: Can use comprehensive trace data
|
|
|
|
## Security Considerations
|
|
|
|
### Sensitive Data
|
|
|
|
Tracing can expose sensitive information. Always:
|
|
|
|
1. Use `sanitizeAttributes: true` (default)
|
|
2. Review trace data before sharing
|
|
3. Consider disabling tracing for production testing
|
|
|
|
### Performance
|
|
|
|
Tracing adds overhead:
|
|
|
|
- Fetching traces: ~100-500ms per iteration
|
|
- Processing spans: Minimal overhead
|
|
- Storage: Trace metadata is stored in test results
|
|
|
|
To minimize impact:
|
|
|
|
- Use `maxSpans` to limit data fetched
|
|
- Set appropriate `maxRetries` and `retryDelayMs`
|
|
- Consider disabling for large-scale testing
|
|
|
|
## Debugging
|
|
|
|
### Enable Debug Logging
|
|
|
|
```bash
|
|
PROMPTFOO_LOG_LEVEL=debug npm run local -- eval -c redteam.yaml
|
|
```
|
|
|
|
### Check Trace Store
|
|
|
|
Verify traces are being recorded:
|
|
|
|
```bash
|
|
# View traces in the database
|
|
npm run db:studio
|
|
```
|
|
|
|
### Test Trace Fetching
|
|
|
|
```typescript
|
|
import { fetchTraceContext } from './src/tracing/traceContext';
|
|
|
|
const trace = await fetchTraceContext('your-trace-id', {
|
|
maxSpans: 50,
|
|
maxDepth: 5,
|
|
});
|
|
console.log(trace);
|
|
```
|
|
|
|
## Examples
|
|
|
|
See the example configurations:
|
|
|
|
- `promptfooconfig.yaml` - Basic tracing setup
|
|
- `promptfooconfig.advanced.yaml` - Advanced configuration
|
|
- `promptfooconfig-simple.yaml` - Simplified configuration
|
|
|
|
## Troubleshooting
|
|
|
|
### No Traces Appearing
|
|
|
|
1. Check that your provider supports tracing (must send traceparent header)
|
|
2. Verify OTLP receiver is running
|
|
3. Check debug logs for trace fetch errors
|
|
|
|
### Traces Not Used in Attacks
|
|
|
|
1. Verify `includeInAttack: true`
|
|
2. Check that traces are being fetched (debug logs)
|
|
3. Ensure trace fetch completes before attack generation
|
|
|
|
### Performance Issues
|
|
|
|
1. Reduce `maxSpans` and `maxDepth`
|
|
2. Use `spanFilter` to limit data
|
|
3. Increase `retryDelayMs` to reduce fetch frequency
|