Token-Count Aware Variant Lorebook Template
Progressive Sentence Lorebook Template
(Token-Count Aware Variant)
A token-aware lorebook system for JanitorAI Scripts that builds context sentence-by-sentence based on priority tiers, with configurable message history scope per subject.
Note: I've not yet had time to test this, I created this based on a conversation with FreeloaderEX. It SHOULD work fine, but there's also a chance my LLM borked it when I had it fix all my stream-of-consciousness comments.
Table of Contents
Overview
Key Differences from Adaptive Template
How It Works
Priority Tier System
Dynamic Tier System
History Scope System
Budget Allocation
Subject Structure
Configuration Options
Setup Instructions
Writing Effective Sentences
Usage Examples
Best Practices
Troubleshooting
Overview
This template provides granular control over lore injection by treating each subject as an array of prioritized sentences rather than switching between full/summary/bullet versions. The system builds output incrementally using round-robin allocation within priority tiers.
Key Differences from Adaptive Template
Adaptive Template:
Content structure: 3 versions (full/summary/bullet)
Selection method: Switch entire version
Multi-subject balance: Top entries get full, others compressed
History awareness: Current message only
Budget allocation: Global reduction passes
Progressive Template:
Content structure: Array of 6-12 sentences
Selection method: Add sentences one-by-one
Multi-subject balance: Round-robin ensures all subjects get coverage
History awareness: Configurable per subject
Budget allocation: Tier-based with current/historical split
When to use Progressive:
You want fine-grained control over which details appear
Multiple subjects should get balanced coverage
Some topics should persist across message turns
You need different history behaviors for different subjects
When to use Adaptive:
You prefer simpler full/summary/bullet approach
Single dominant topic per message is common
All subjects use same history scope
Faster to set up for simple scenarios
How It Works
Detection: Keywords in messages activate subjects
Scope Resolution: Each subject checks its configured history scope
Mention Counting: Count mentions in the appropriate message context
Tier Assignment: Subjects sorted into HIGH/MEDIUM/LOW tiers by mention count
Pool Splitting: Each tier split into current vs historical pools
Budget Calculation: Token budgets calculated per tier per pool
Round-Robin Building: Sentences added one-by-one across subjects in each pool
Application: Built sentences added to character context
Priority Tier System
Subjects are assigned to tiers based on mention count:
HIGH Tier (default: 3+ mentions)
Receives 60% of token budget
Most detailed coverage
First sentences from each subject guaranteed
MEDIUM Tier (default: 2 mentions)
Receives 25% of token budget
Moderate coverage
Key details included
LOW Tier (default: 1 mention)
Receives 15% of token budget
Essential facts only
May only get first 1-2 sentences per subject
Tier Threshold Configuration
const CONFIG = {
HIGH_THRESHOLD: 3, // 3+ mentions = high tier
MEDIUM_THRESHOLD: 2, // 2 mentions = medium tier
// 1 mention = low tier (implicit)
};
Dynamic Tier System
The dynamic tier system optimizes budget usage when tiers are underfilled. It provides two mechanisms:
Budget Redistribution
When DYNAMIC_BUDGETS: true, unused budget from higher tiers flows to lower tiers.
Example Scenario:
HIGH tier budget: 900 tokens
HIGH tier subjects only need: 200 tokens
Unused: 700 tokens redistributed to MEDIUM/LOW
Redistribution Modes:
cascade: HIGH unused goes to MEDIUM, then MEDIUM unused goes to LOWproportional: Unused split based on remaining tiers' needslow_priority: All unused goes directly to LOW tier
// Cascade mode (default) // 700 unused from HIGH goes to MEDIUM // If MEDIUM still has 400 unused after that, it goes to LOW// Proportional mode // If MEDIUM needs 300 more and LOW needs 600 more // MEDIUM gets 233 (300/900 * 700), LOW gets 467
// Low priority mode // All 700 goes straight to LOW tier
Subject Promotion
When PROMOTION_ENABLED: true, subjects can be promoted to higher tiers if those tiers are empty.
How it works:
If HIGH tier is empty, promote top subject from MEDIUM (if importance meets threshold)
If MEDIUM tier is empty (after promotion), promote top subject from LOW
Only subjects meeting
PROMOTION_MIN_IMPORTANCEare eligible
Example:
User mentions only "the Duke" once (normally LOW tier)
HIGH and MEDIUM tiers are empty
Duke has importance 9.0 (meets threshold of 5.0)
Duke gets promoted to HIGH tier, receives 60% budget instead of 15%
Dynamic Configuration
const CONFIG = { // Enable/disable dynamic features DYNAMIC_BUDGETS: true, PROMOTION_ENABLED: true,// Minimum importance to be promotion-eligible PROMOTION_MIN_IMPORTANCE: 5.0, // Redistribution strategy REDISTRIBUTION_MODE: 'cascade', // 'cascade', 'proportional', or 'low_priority'
};
When to Use Each Mode
Cascade (default):
Balanced approach
Good for most scenarios
Higher tiers get first chance at extra budget
Proportional:
Fair distribution based on need
Best when all tiers matter equally
Prevents any tier from being starved
Low Priority:
Maximizes coverage of low-mention subjects
Good for broad exploration scenarios
Ensures minor subjects get adequate detail
Disabling Dynamic Features
Set both to false for static tier behavior:
DYNAMIC_BUDGETS: false,
PROMOTION_ENABLED: false,
This gives predictable, fixed budget allocation regardless of what activates.
History Scope System
Each subject can specify which messages to consider for keyword detection:
CURRENT_USER_ONLY
Only looks at the user's most recent message.
Use for:
Historical events (only relevant when directly asked)
Minor characters
Specific mechanics or rules
Topics that shouldn't "linger"
historyScope: HISTORY_SCOPE.CURRENT_USER_ONLY
CURRENT_EXCHANGE
Looks at both the user's message and the AI's last response.
Use for:
Active NPCs in a scene
Current location details
Ongoing conversations
Topics that should persist through a turn
historyScope: HISTORY_SCOPE.CURRENT_EXCHANGE
HISTORICAL
Looks back N messages (configurable).
Use for:
Major factions the player has engaged with
Ongoing plot threads
Persistent threats or relationships
Topics that should remain in context
historyScope: HISTORY_SCOPE.HISTORICAL
// Controlled by CONFIG.HISTORY_MESSAGE_COUNT
Budget Allocation
Tier Budgets
Total budget is split by configurable ratios:
TOTAL_BUDGET: 1500,
HIGH_RATIO: 0.60, // 900 tokens for high tier
MEDIUM_RATIO: 0.25, // 375 tokens for medium tier
LOW_RATIO: 0.15, // 225 tokens for low tier
Current vs Historical Pools
Each tier's budget is further split:
CURRENT_BUDGET_RATIO: 0.70, // 70% for current-scope subjects
HISTORICAL_BUDGET_RATIO: 0.30, // 30% for historical-scope subjects
This ensures subjects using historical scope don't crowd out immediate context.
Example Budget Breakdown
Total: 1500 tokens
HIGH Tier (900 tokens):
- Current pool: 630 tokens
- Historical pool: 270 tokens
MEDIUM Tier (375 tokens):
- Current pool: 262 tokens
- Historical pool: 113 tokens
LOW Tier (225 tokens):
-
Current pool: 157 tokens
Historical pool: 68 tokens
Subject Structure
Each subject in the database follows this structure:
{
id: 'unique_identifier',
keywords: ['trigger', 'words', 'phrases'],
importance: 8.5, // Float for tiebreaking within tiers
historyScope: HISTORY_SCOPE.CURRENT_EXCHANGE,
sentences: [
{ text: ' Most important fact about this subject.', target: 'scenario' },
{ text: ', key personality trait related to subject', target: 'personality' },
{ text: ' Second most important detail.', target: 'scenario' },
{ text: ' Additional context.', target: 'scenario' },
{ text: ', secondary personality trait', target: 'personality' },
{ text: ' Deep lore detail.', target: 'scenario' },
// ... up to 12 sentences
]
}
Field Descriptions
id: Unique identifier for debugging
keywords: Trigger words/phrases (case-insensitive)
importance: Tiebreaker when subjects have equal mentions
historyScope: Which messages to search for keywords
sentences: Ordered list of sentence objects
Sentence Object
text: The sentence to inject (include leading space)
target:
'personality'or'scenario'
Configuration Options
const CONFIG = { // Budget settings TOTAL_BUDGET: 1500, // Total available tokens HIGH_RATIO: 0.60, // High tier percentage MEDIUM_RATIO: 0.25, // Medium tier percentage LOW_RATIO: 0.15, // Low tier percentage (remainder)// Tier thresholds HIGH_THRESHOLD: 3, // Mentions needed for high tier MEDIUM_THRESHOLD: 2, // Mentions needed for medium tier
// History settings HISTORY_MESSAGE_COUNT: 10, // Messages to search for HISTORICAL scope
// Pool split ratios CURRENT_BUDGET_RATIO: 0.70, // Current-scope budget share HISTORICAL_BUDGET_RATIO: 0.30, // Historical-scope budget share
// Dynamic tier settings DYNAMIC_BUDGETS: true, // Redistribute unused budget to lower tiers PROMOTION_ENABLED: true, // Promote subjects to empty higher tiers PROMOTION_MIN_IMPORTANCE: 5.0, // Minimum importance for promotion eligibility REDISTRIBUTION_MODE: 'cascade', // 'cascade', 'proportional', or 'low_priority'
// Debug DEBUG: false // Show activation info in output };
Configuration Reference
TOTAL_BUDGET: Maximum tokens for all lore (default: 1500)
HIGH_RATIO: Budget share for high tier (default: 0.60)
MEDIUM_RATIO: Budget share for medium tier (default: 0.25)
LOW_RATIO: Budget share for low tier (default: 0.15)
HIGH_THRESHOLD: Mentions needed for high tier (default: 3)
MEDIUM_THRESHOLD: Mentions needed for medium tier (default: 2)
HISTORY_MESSAGE_COUNT: Messages to search for HISTORICAL scope (default: 10)
CURRENT_BUDGET_RATIO: Pool share for current-scope subjects (default: 0.70)
HISTORICAL_BUDGET_RATIO: Pool share for historical-scope subjects (default: 0.30)
DYNAMIC_BUDGETS: Enable budget redistribution (default: true)
PROMOTION_ENABLED: Enable subject promotion (default: true)
PROMOTION_MIN_IMPORTANCE: Minimum importance for promotion (default: 5.0)
REDISTRIBUTION_MODE: How to redistribute unused budget (default: 'cascade')
DEBUG: Show debug info in output (default: false)
Setup Instructions
Copy
Progressive_Sentence_Lorebook_Template.jsto your JanitorAI ScriptsAdjust CONFIG values for your scenario
Replace example subjects with your world content
Order sentences within each subject by importance
Set appropriate history scope for each subject
Test with
DEBUG: trueenabledFine-tune thresholds and budgets based on results
Writing Effective Sentences
Sentence Ordering
Order sentences from most to least important within each subject:
First sentence: Core identity/definition (always included if subject activates)
Second sentence: Primary personality trait OR key detail
Third-fourth sentences: Important relationships and context
Middle sentences: Significant background information
Later sentences: Flavor details, deep lore, optional nuance
Writing Guidelines
DO:
Start scenario sentences with a space
Start personality sentences with a comma and space
Make each sentence meaningful standalone
Include mix of scenario and personality targets
Keep sentences focused on single facts
DON'T:
Start sentences with conjunctions (unless continuing thought)
Include redundant information across sentences
Put the most interesting details last
Make sentences dependent on previous sentences
Example - Good Sentence Set
sentences: [
{ text: ' The Crimson Order is an elite military unit serving the Emperor directly.', target: 'scenario' },
{ text: ', respectful of the Crimson Order's legendary combat prowess', target: 'personality' },
{ text: ' They answer to no noble house and operate above normal military law.', target: 'scenario' },
{ text: ' Membership requires surviving brutal trials and absolute loyalty oaths.', target: 'scenario' },
{ text: ' Their signature crimson cloaks are both feared and respected.', target: 'scenario' },
{ text: ', aware that crossing the Crimson Order rarely ends well', target: 'personality' },
{ text: ' Rumors persist of their involvement in political assassinations.', target: 'scenario' }
]
Usage Examples
Example 1: Single Subject, High Mentions
User message: "Tell me more about the Duke. What is Duke Ashford planning? The Duke seems suspicious."
Result:
Duke Ashford subject: 3 mentions ("Duke" x3)
Placed in HIGH tier
Gets full high-tier budget allocation
Most/all sentences added
Example 2: Multiple Subjects, Balanced
User message: "What do the Mages Guild and Merchant Guild think of each other?"
Result:
Mages Guild: 1 mention
Merchant Guild: 1 mention
Both in LOW tier (1 mention each)
Round-robin allocation: Mages sentence 1, Merchant sentence 1, Mages sentence 2, etc.
Balanced coverage of both topics
Example 3: Historical vs Current
Setup:
Duke Ashford: CURRENT_EXCHANGE scope
Merchant Guild: HISTORICAL scope (discussed 5 messages ago)
User message: "What does the Duke think about trade?"
Result:
Duke Ashford: Activated (mentioned in current message)
Merchant Guild: Also activated (mentioned in historical context, "trade" keyword)
Duke uses current pool, Merchant uses historical pool
Both get coverage without competing for same budget
Example 4: Dynamic Budget Redistribution
Setup:
DYNAMIC_BUDGETS: true
REDISTRIBUTION_MODE: 'cascade'
Total budget: 1500 tokens
User message: "Tell me about the capital."
What happens:
Only "capital" subject activates (1 mention, normally LOW tier)
HIGH tier: empty (budget 900, needs 0) - 900 unused
MEDIUM tier: empty (budget 375, needs 0) - 375 unused
CASCADE redistribution kicks in:
HIGH's 900 unused goes to MEDIUM (now has 1275)
MEDIUM's 1275 unused goes to LOW (now has 1500)
LOW tier now has full 1500 token budget
Capital subject gets ALL its sentences instead of just 1-2
Result: Single subject gets comprehensive coverage instead of minimal detail.
Example 5: Subject Promotion
Setup:
PROMOTION_ENABLED: true
PROMOTION_MIN_IMPORTANCE: 5.0
Duke Ashford importance: 9.0
User message: "What is the Duke planning?"
What happens:
Only Duke activates (1 mention, normally LOW tier)
HIGH tier empty, MEDIUM tier empty
Promotion checks Duke's importance (9.0 meets 5.0 threshold)
Duke promoted directly to HIGH tier
Duke receives HIGH tier budget (60% = 900 tokens)
Result: Important single-subject queries get the detail they deserve.
Example 6: Combined Dynamic Features
Setup:
Both DYNAMIC_BUDGETS and PROMOTION_ENABLED: true
Three subjects: Duke (importance 9.0), Mages Guild (8.5), Great War (5.0)
User message: "The Duke and the mages fought in the war."
What happens:
All three subjects activate with 1 mention each (normally all LOW)
HIGH tier empty - Duke promoted to HIGH (importance 9.0)
MEDIUM tier empty - Mages Guild promoted to MEDIUM (importance 8.5)
Great War stays in LOW (importance 5.0, but no empty tiers left)
Budget redistribution:
HIGH tier: Duke needs ~400 tokens, has 900 - 500 unused
500 cascades to MEDIUM - Mages Guild now has 875 tokens
MEDIUM needs ~350, has 875 - 525 unused
525 cascades to LOW - Great War now has 750 tokens
All subjects get expanded coverage
Result: Balanced, detailed coverage across multiple subjects with intelligent budget allocation.
Best Practices
Budget Tuning
Start with default ratios and adjust based on testing
Lower HIGH_THRESHOLD if single mentions feel under-served
Increase TOTAL_BUDGET for complex scenes
Decrease TOTAL_BUDGET for faster models or simpler scenarios
History Scope Selection
Default to CURRENT_USER_ONLY for most subjects
Use CURRENT_EXCHANGE for active scene elements
Reserve HISTORICAL for truly persistent elements
Too many HISTORICAL subjects can bloat context
Keyword Design
Include common variations and synonyms
Add character titles and nicknames
Consider partial matches ("duke" catches "Duke Ashford")
Avoid overly generic keywords that activate unintentionally
Testing Strategy
Enable DEBUG mode
Send test messages with various keyword combinations
Verify tier assignments match expectations
Check sentence counts per subject
Ensure important info appears first
Test edge cases (no keywords, many keywords, etc.)
Troubleshooting
Too Much Content Added
Solutions:
Lower TOTAL_BUDGET
Raise tier thresholds
Reduce sentence counts per subject
Lower HISTORICAL_BUDGET_RATIO
Important Subjects Getting Cut
Solutions:
Increase their importance value
Lower tier thresholds
Move critical info to first sentences
Adjust tier budget ratios
Historical Subjects Dominating
Solutions:
Lower HISTORICAL_BUDGET_RATIO
Reduce HISTORY_MESSAGE_COUNT
Change some subjects to CURRENT_USER_ONLY
Be more selective with HISTORICAL scope
Unbalanced Coverage
Solutions:
Check mention counts in DEBUG output
Verify tier assignments are as expected
Consider adjusting keyword specificity
May need to adjust thresholds
Sentences Appearing Out of Order
This is expected - round-robin adds one sentence per subject at a time. Important info should be in first sentences of each subject. The alternating pattern ensures balance across subjects.
Performance Issues
Solutions:
Reduce subject count
Lower HISTORY_MESSAGE_COUNT
Simplify keyword patterns
Consider splitting into multiple scripts if needed
Created for the Janitor AI Scripts community. Feel free to modify, share, and improve upon this system.
Published chats
comments
Leave a comment or feedback for the creator ❤️