Skip to main content

context_forge/lexicon/
bootstrap.rs

1//! Prompt template for bootstrapping a persona-specific [`super::ConfigLexiconScorer`].
2
3/// Generate a calibration prompt for bootstrapping a persona lexicon via an LLM.
4///
5/// Pass the returned string to any LLM. The model's response will be a fenced TOML
6/// block suitable for parsing with [`super::ConfigLexiconScorer::from_str`] or saving
7/// to disk for [`super::ConfigLexiconScorer::from_file`].
8///
9/// CF provides the calibration baseline; the caller is responsible for making the
10/// LLM call and persisting the result. Extract the TOML from inside the fenced block
11/// before parsing.
12///
13/// # Example
14///
15/// ```
16/// use context_forge::lexicon::bootstrap_prompt;
17///
18/// let prompt = bootstrap_prompt("A Space Marine Chaplain from Warhammer 40k");
19/// assert!(prompt.contains("Space Marine Chaplain"));
20/// assert!(prompt.contains("0.0, 1.5]"));
21/// ```
22#[must_use]
23pub fn bootstrap_prompt(persona_description: &str) -> String {
24    format!(
25        r#"You are generating a lexicon configuration for a memory importance scoring system.
26
27The AI assistant using this lexicon has the following persona:
28<persona>
29{persona_description}
30</persona>
31
32## What this lexicon does
33
34This lexicon teaches a deterministic scoring system which domain-specific terms and phrases
35signal "this conversation entry is worth remembering." Entries that score higher survive a
36token budget cut and are surfaced in future conversations.
37
38The scoring formula is:
39  final_score = base_score × (1.0 + boost.clamp(-1.0, 2.0))
40
41Where boost accumulates as follows:
42  - Each matched [terms] entry adds its weight directly to boost
43  - Each matched [affirmations] pattern adds +0.5 to boost
44  - Each matched [negations] pattern subtracts 0.3 from boost
45
46A boost of 0.0 leaves the score unchanged. A boost of 1.0 doubles it (2.0×).
47The engine caps total boost at 2.0, giving a 3.0× maximum multiplier.
48
49## Weight calibration
50
51| Range     | Use for                                                                          |
52|-----------|----------------------------------------------------------------------------------|
53| 0.1–0.4   | Mildly domain-specific. Appears in casual and important content alike.           |
54| 0.5–0.8   | Strongly domain-specific. More often in important entries than not.              |
55| 0.9–1.5   | Critical term or proper noun. Almost always marks high-value content.            |
56
57Weights must be in (0.0, 1.5]. Never assign a weight above 1.5; the library will
58reject any config that does.
59
60## Inclusion rules for [terms]
61
621. Minimum 4 characters, unless the term is a well-known domain acronym.
632. Prefer precise multi-word phrases over short, ambiguous single words.
643. Memory-value test: include a term ONLY if its presence in an entry makes that entry
65   meaningfully more likely to be worth recalling later. Do not include terms merely
66   because they sound authentic or in-character for the persona.
67
68## What NOT to include
69
70The system already handles generic English signals ("confirmed", "agreed", "remember this",
71"never mind", "my mistake", "incorrect", and similar). Do not repeat them. Only
72domain-specific vocabulary and dialect belong in this lexicon.
73
74## [affirmations] — speech act rules
75
76Affirmation patterns must map to one of these speech acts in this persona's dialect:
77  - Agreement or confirmation
78  - Future commitment or obligation
79  - Success or resolution
80  - Flagging something as important or worth noting
81
82Aim for 6–12 patterns. Domain-specific dialect only — no generic English.
83
84## [negations] — speech act rules
85
86Negation patterns must map to one of these speech acts in this persona's dialect:
87  - Dismissal or disregard
88  - Disagreement or correction
89  - Failure or rejection
90
91Aim for 4–8 patterns. Domain-specific dialect only — no generic English.
92
93## Output instructions
94
95Think through the calibration internally before writing any output. Reason about which
96terms are genuinely high-signal vs. merely in-character, and what speech acts this
97persona's dialect uses to express agreement, commitment, dismissal, and failure.
98
99Then output ONLY a single fenced TOML block. No markdown, no prose before or after
100the block. Put short rationale as valid TOML inline comments.
101
102```toml
103# Persona lexicon — generated for context-forge
104# Persona: {persona_description}
105
106[terms]
107"term" = 0.4   # rationale: why this term signals important content
108
109[affirmations]
110patterns = [
111    "phrase",   # speech act: confirmation
112]
113
114[negations]
115patterns = [
116    "phrase",   # speech act: dismissal
117]
118```"#,
119    )
120}