import DocInfo from '@site/src/components/DocInfo';
FSD: M65 - Redaction and Contextual Abstraction Service
Status: 🔄 Enhancement Proposal | Version: 2.0 | Last Updated: 2025-11-11
1. Overview
This document specifies the functional requirements for enhancing the Redaction and Contextual Abstraction Service. The service's primary purpose is to enable the use of Large Language Models (LLMs) with sensitive or proprietary data. This enhancement focuses on token efficiency optimization and unified API design based on tokenization research findings.
1.1 Scope
- Current Implementation:
python-services/redaction-engine-service/(v1.0) - Target State: Token-efficient placeholders with unified
/redact+ new/unredactendpoint - Key Driver: Reduce LLM token costs by 60-80% through optimized placeholder design
1.2 Related Research
See docs/strategy-and-research/redaction-tokenization.md for detailed analysis of:
- Subword tokenization mechanics (BPE, WordPiece)
- Placeholder token efficiency comparison
- Session map architecture rationale
2. Current State Analysis
2.1 Existing Implementation
Service Location: python-services/redaction-engine-service/app.py
Current Endpoints:
POST /redact- Sanitizes text with UUID-based placeholdersPOST /abstractize- Converts entities to category tokensPOST /metadata-for-llm- Generates metadata injection stringsGET /health- Health check
Current Placeholder Strategy:
# Example from app.py:219-220
redacted_val_with_id = f"{base_redacted_val}_{unique_id}"
# Result: "[REDACTED_EMAIL]_a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8"
2.2 Token Efficiency Problem
Current Tokenization:
Input: "Contact john@acme.com"
Redacted: "Contact [REDACTED_EMAIL]_a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8"
Tokens: ["Contact", " ", "[", "REDA", "CTED", "_", "EMAIL", "]", "_", "a", "1", "b", "2", ... ]
= ~40 tokens per entity
Target Tokenization:
Input: "Contact john@acme.com"
Redacted: "Contact Email1"
Tokens: ["Contact", " ", "Email", "1"]
= 4 tokens per entity
Cost Impact: 90% token reduction per redacted entity
2.3 Gap Analysis
| Feature | Current State | Target State | Priority |
|---|---|---|---|
| Placeholder Format | [REDACTED_EMAIL]_uuid (40 tokens) | Email1 (2 tokens) | 🔴 Critical |
| Session State | Returned as redaction_mapping | Returned as session_map | 🟡 Medium |
| Unredaction | ❌ Not implemented | POST /unredact endpoint | 🔴 Critical |
| Unified API | Separate /redact + /abstractize | Single /redact with metadata | 🟢 Low |
| Metadata Injection | ✅ Already implemented (plain text + JSON) | ✅ Keep as-is | ✅ Complete |
3. Target Architecture: The "Session Map" Approach
The service will follow the "Session Map" architecture to ensure security, efficiency, and high-quality LLM performance. The workflow is as follows:
- Processing: The service receives raw text. It identifies sensitive entities and replaces them with short, unique placeholders (e.g.,
Brand1,Person1). Note: Research showsBrand1(2 tokens) is more efficient thanBRAND_1(3 tokens) due to PascalCase being common in training data. - State Management: During processing, the service generates a
session_mapobject. This map links each placeholder to its original value and is returned to the calling client. This map is never sent to the LLM. - Context Generation: For entities with known attributes, the service generates a plain-text
metadata_injectionstring to be included in the LLM's system prompt. - LLM Interaction: The client sends the
sanitized_textandmetadata_injectionto the LLM. - Unredaction: The client receives the response from the LLM and sends it, along with the original
session_map, to the service's unredaction endpoint to restore the original sensitive values.
3. Functional Requirements
The service will expose two primary endpoints. The existing /redact endpoint will be refactored, and a new /unredact endpoint will be created.
3.1. Unified Processing Endpoint: POST /redact
This endpoint handles the entire redaction and context-generation process.
- Request Body:
{
"text": "<The raw input string to be processed>",
"tenant_id": "<The ID of the tenant to apply rules for>"
} - Processing Logic:
- Identify all sensitive entities in the
textbased on tenant-specific rules (PII, proprietary patterns, customer names, etc.). - For each unique entity found, generate a token-efficient placeholder (e.g.,
[TYPE]_[COUNT], likeEMAIL_1). These placeholders must be designed to be unambiguous and distinct from natural language to ensure the unredaction logic can operate reliably. - Construct the
session_mapobject, linking each placeholder to its original value and type. - Use the
ContextualAbstractionManagerto generate themetadata_injectionstring for all identified entities that have contextual metadata. - Produce the
sanitized_textby replacing the original entities with their corresponding placeholders.
- Identify all sensitive entities in the
- Response Body:
{
"sanitized_text": "<Text with placeholders>",
"session_map": {
"PLACEHOLDER_1": { "original": "value1", "type": "TYPE_A", "sensitivity": "low" },
"PLACEHOLDER_2": { "original": "value2", "type": "TYPE_B", "sensitivity": "high" }
},
"metadata_injection": "<Plain-text context for the LLM system prompt>"
}
3.2. Unredaction Endpoint: POST /unredact
This endpoint restores the original text from an LLM response.
- Request Body:
{
"text": "<The LLM's response, containing placeholders>",
"session_map": {
"PLACEHOLDER_1": { "original": "value1", ... },
"PLACEHOLDER_2": { "original": "value2", ... }
}
} - Processing Logic:
- Iterate through the
session_mapkeys (placeholders). - For each placeholder, perform a robust, case-insensitive replacement on the input
text. - The replacement logic must be "word-aware" to correctly handle placeholders adjacent to common punctuation (e.g.,
.,,,?,)) without affecting partial-string matches. A regular expression using word boundaries (e.g.,\b) is the recommended approach.
- Iterate through the
- Response Body:
{
"unredacted_text": "<The LLM's response with original values restored>"
}
4. Non-Functional Requirements
- Performance: The service must have low latency to be used in near real-time applications. Caching for tenant-specific rules and data will be critical.
- Security: The
session_mapcontains sensitive data and must be handled securely by the calling client. It should not be logged or stored unnecessarily. - Statelessness: The service itself remains stateless. The state (
session_map) is owned and managed by the client, which aligns with modern cloud-native principles.
5. End-to-End Example
Complete Workflow
Step 1: Client calls /redact
POST /redact
{
"text": "Contact john@acme.com about ACME Corp's Q4 revenue of $2.5M",
"tenant_id": "tenant-123"
}
Step 2: Service Response
{
"sanitized_text": "Contact Email1 about Brand1's Q4 revenue of Currency1",
"session_map": {
"Email1": {
"original": "john@acme.com",
"type": "EMAIL",
"sensitivity": "high"
},
"Brand1": {
"original": "ACME Corp",
"type": "BRAND",
"sensitivity": "low"
},
"Currency1": {
"original": "$2.5M",
"type": "CURRENCY",
"sensitivity": "medium"
}
},
"metadata_injection": "Brand1 is a B2B software company in the enterprise SaaS space with 35% margin."
}
Step 3: Client constructs LLM Prompt
System: You are analyzing business communications. Context:
Brand1 is a B2B software company in the enterprise SaaS space with 35% margin.
User: Contact Email1 about Brand1's Q4 revenue of Currency1
Step 4: LLM Responds
"I'll draft an email to Email1 discussing Brand1's strong Q4 performance (Currency1 represents 15% growth YoY)."
Step 5: Client calls /unredact
POST /unredact
{
"text": "I'll draft an email to Email1 discussing Brand1's strong Q4 performance (Currency1 represents 15% growth YoY).",
"session_map": { /* same as from /redact */ }
}
Step 6: Service Response
{
"unredacted_text": "I'll draft an email to john@acme.com discussing ACME Corp's strong Q4 performance ($2.5M represents 15% growth YoY)."
}
6. Migration Strategy
6.1 Backward Compatibility
Approach: Dual-format support during transition period
# app.py enhancement
def get_placeholder_format(tenant_config):
"""Allow per-tenant format selection"""
if tenant_config.get('use_v2_placeholders'):
return 'efficient' # Brand1, Email1
return 'legacy' # [REDACTED_BRAND]_uuid
6.2 Migration Phases
Phase 1: Implement v2 (Week 1-2)
- Add counter-based placeholder generation
- Implement
/unredactendpoint - Add format selection parameter to
/redact - Deploy as opt-in feature
Phase 2: Testing (Week 3)
- Internal testing with ChainAlign tenant
- A/B cost comparison (UUID vs. counters)
- Validate unredaction accuracy
Phase 3: Gradual Rollout (Week 4-6)
- Enable v2 for new tenants by default
- Migrate existing tenants one-by-one
- Monitor token cost reductions
Phase 4: Deprecation (Month 3)
- Announce deprecation of UUID format
- Provide 90-day migration window
- Remove legacy code in v3.0 release
6.3 Risk Mitigation
Risk: Placeholder collision in existing text Mitigation: Pre-scan for collision, use session-specific prefixes if detected
Risk: Case-sensitivity in unredaction Mitigation: Implement case-insensitive + word-boundary regex (already specified in FSD)
Risk: LLM hallucinates non-existent placeholders
Mitigation: Return unmapped_placeholders array in /unredact response for logging
7. Success Metrics
| Metric | Baseline (v1) | Target (v2) | Measurement |
|---|---|---|---|
| Avg tokens/entity | 40 | 2-3 | Log analysis |
| Token cost reduction | N/A | 60-80% | Monthly billing |
| Unredaction accuracy | N/A | 99.9% | Automated tests |
| API latency (p95) | <500ms | <500ms | Monitoring |
8. References
- Research Document:
docs/strategy-and-research/redaction-tokenization.md - Current Implementation:
python-services/redaction-engine-service/app.py - Related Services:
python-services/meta-prompting-service/ - Tokenization Paper: BPE: Neural Machine Translation of Rare Words with Subword Units