# Thinking To Recall

> Demonstrates that chain-of-thought reasoning improves LLM factual retrieval through computational buffering and self-priming. Improves single-hop factual accuracy by enabling models to generate contextual bridge facts before recalling answers.

- Skill: `adu2021/thinking-to-recall` (Agent Skill)
- Install (CLI): `npx skillmds@latest add adu2021/thinking-to-recall`
- Raw SKILL.md: https://api.skillmd.com/api/skills/adu2021/thinking-to-recall/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: adu2021 (https://skillmd.com/u/adu2021)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/adu2021/thinking-to-recall

---


# Thinking to Recall: Unlocking Parametric Knowledge Through Reasoning

LLMs perform well on multi-hop reasoning tasks but surprisingly struggle on simple single-hop factual questions that require no complex logic. Enabling chain-of-thought reasoning dramatically improves performance on these supposedly simple queries. The question: why does reasoning help when the task requires no reasoning?

Through controlled experiments isolating different reasoning effects, this skill reveals three mechanisms: computational buffering (generating tokens to "warm up"), factual priming (recalling related facts that enable main answer), and verification (intermediate facts provide checkpoints). By understanding these mechanisms, you can optimize prompting strategies for pure factual retrieval tasks.

## Core Concept

Reasoning doesn't just help complex tasks—it unlocks parametric knowledge on simple factual questions through:

1. **Computational Buffer**: Model generates reasoning tokens independently of semantic content; this computation alone improves main answer quality (even with random text of same length)

2. **Factual Priming**: Model generates topically related facts during reasoning that serve as "bridges" to the target answer, like priming in human memory

3. **Hallucination Detection**: Intermediate facts in reasoning traces can be verified, identifying when the trajectory will fail

## Architecture Overview

- **Chain-of-Thought Prompting**: Request thinking before answering for simple facts
- **Intermediate Fact Extraction**: Parse generated reasoning to identify stated facts
- **Fact Verification**: Cross-check extracted facts against knowledge bases
- **Trajectory Quality Assessment**: Predict answer correctness from intermediate fact validity
- **Calibration**: Only prioritize high-confidence reasoning trajectories

## Implementation Steps

Implement fact-aware reasoning with intermediate verification to improve single-hop factual recall.

**Compute Reasoning Effect Isolation**

```python
import torch
from typing import List, Tuple

class ReasoningEffectAnalyzer:
    """Analyze what component of reasoning improves factual recall."""

    def __init__(self, model, tokenizer, knowledge_base):
        self.model = model
        self.tokenizer = tokenizer
        self.kb = knowledge_base  # Database of verified facts

    def measure_reasoning_benefit(self, question: str, ground_truth: str) -> dict:
        """
        Measure three components of reasoning benefit.

        Args:
            question: factual question
            ground_truth: correct answer

        Returns:
            effects: dict with {computational_buffer, factual_priming, verification}
        """
        effects = {}

        # Baseline: direct answer without reasoning
        direct_answer = self._get_direct_answer(question)
        baseline_correct = direct_answer == ground_truth

        # Condition 1: Reasoning with semantic content
        reasoning_output = self._get_reasoning_output(question)
        reasoning_answer = self._extract_answer(reasoning_output)
        reasoning_correct = reasoning_answer == ground_truth

        # Condition 2: Computational buffer (meaningless text of same length)
        filler_length = len(reasoning_output.split())
        filler_text = " ".join(["filler"] * filler_length)
        buffer_prompt = f"{question}\n{filler_text}\nAnswer:"
        buffer_answer = self._get_answer_from_prompt(buffer_prompt)
        buffer_correct = buffer_answer == ground_truth

        effects['computational_buffer'] = (buffer_correct and not baseline_correct)

        # Condition 3: Extract facts from reasoning and measure priming
        facts_in_reasoning = self._extract_facts(reasoning_output)
        related_facts = [f for f in facts_in_reasoning if self._is_related_to_question(f, question)]
        effects['factual_priming'] = len(related_facts) > 0

        # Condition 4: Fact verification predicts answer correctness
        facts_verified = [self._verify_fact(f) for f in facts_in_reasoning]
        effects['verification_accuracy'] = sum(facts_verified) / (len(facts_verified) + 1e-6)

        # Overall improvement
        effects['baseline_correct'] = baseline_correct
        effects['reasoning_correct'] = reasoning_correct
        effects['improvement'] = reasoning_correct and not baseline_correct

        return effects

    def _get_direct_answer(self, question: str) -> str:
        """Get model's direct answer without reasoning."""
        prompt = f"{question}\nAnswer:"
        return self._get_answer_from_prompt(prompt)

    def _get_reasoning_output(self, question: str) -> str:
        """Get model's reasoning trajectory."""
        prompt = f"{question}\nLet me think about this step by step:"
        return self._get_answer_from_prompt(prompt)

    def _extract_answer(self, reasoning_output: str) -> str:
        """Extract final answer from reasoning output."""
        # Simplified: assume answer appears after "Answer:" or at end
        if "Answer:" in reasoning_output:
            return reasoning_output.split("Answer:")[-1].strip().split('\n')[0]
        return reasoning_output.split('\n')[-1].strip()

    def _extract_facts(self, text: str) -> List[str]:
        """Extract factual statements from text."""
        # Simplified: split by periods and treat as atomic facts
        sentences = [s.strip() for s in text.split('.') if s.strip()]
        return sentences

    def _is_related_to_question(self, fact: str, question: str) -> bool:
        """Check if fact is related to question topic."""
        question_words = set(question.lower().split())
        fact_words = set(fact.lower().split())
        overlap = len(question_words & fact_words)
        return overlap > 2

    def _verify_fact(self, fact: str) -> bool:
        """Verify if fact is true according to knowledge base."""
        # Query KB for fact verification
        return self.kb.is_true(fact)

    def _get_answer_from_prompt(self, prompt: str) -> str:
        """Get model's response to prompt."""
        input_ids = self.tokenizer.encode(prompt, return_tensors='pt')
        with torch.no_grad():
            output_ids = self.model.generate(
                input_ids, max_new_tokens=50, temperature=0.1
            )
        return self.tokenizer.decode(output_ids[0])
```

**Fact-Aware Reasoning Prompting**

```python
class FactAwareReasoningPrompt:
    """Generate prompts that leverage factual priming."""

    def __init__(self, knowledge_base, model):
        self.kb = knowledge_base
        self.model = model

    def construct_priming_prompt(self, question: str, related_entity: str = None) -> str:
        """
        Construct prompt with factual priming.

        Args:
            question: factual question
            related_entity: optional entity to seed priming

        Returns:
            prompt: formatted prompt with priming hints
        """
        # Extract entities from question if not provided
        if related_entity is None:
            related_entity = self._extract_main_entity(question)

        # Get related facts from KB
        related_facts = self.kb.get_facts_about(related_entity)[:3]  # Top 3 facts

        # Construct prompt with embedded priming
        prompt = f"""Context facts:
{chr(10).join(related_facts)}

Question: {question}
Let me think step by step:"""

        return prompt

    def construct_verification_prompt(self, question: str, reasoning_trace: str) -> str:
        """
        Construct prompt to verify reasoning trace.

        Args:
            question: original question
            reasoning_trace: model-generated reasoning

        Returns:
            prompt: verification prompt
        """
        facts = self._extract_sentences(reasoning_trace)

        verification_prompt = f"""Evaluate the following reasoning for the question: {question}

Reasoning steps:
"""
        for i, fact in enumerate(facts):
            verification_prompt += f"\n{i+1}. {fact}\n"
            verification_prompt += "   Is this fact correct? (yes/no): "

        return verification_prompt

    def _extract_main_entity(self, question: str) -> str:
        """Extract primary entity from question."""
        # Simplified: take longest noun
        words = question.split()
        return max(words, key=len) if words else ""

    def _extract_sentences(self, text: str) -> List[str]:
        """Extract sentences from text."""
        return [s.strip() for s in text.split('.') if s.strip()]


class ReasoingCalibrationModule:
    """Calibrate confidence in reasoning trajectories."""

    def __init__(self, model, knowledge_base):
        self.model = model
        self.kb = knowledge_base

    def calibrate_reasoning_quality(self, question: str, reasoning_trace: str) -> float:
        """
        Estimate correctness probability of reasoning trajectory.

        Args:
            reasoning_trace: model's generated reasoning

        Returns:
            confidence: probability that final answer is correct (0-1)
        """
        # Extract and verify intermediate facts
        facts = self._extract_facts(reasoning_trace)
        verification_scores = []

        for fact in facts:
            # Check fact against KB
            is_true = self.kb.is_true(fact)
            verification_scores.append(1.0 if is_true else 0.0)

        if not verification_scores:
            return 0.5  # Neutral

        # Average verification score with decay for later facts
        # (later facts may be less reliable)
        weighted_verification = sum(
            (1 - 0.1 * i) * score  # Decay later facts by 10%
            for i, score in enumerate(verification_scores)
        ) / len(verification_scores)

        return weighted_verification

    def _extract_facts(self, text: str) -> List[str]:
        """Extract factual claims."""
        return [s.strip() for s in text.split('.') if s.strip()]

    def filter_by_reasoning_quality(
        self,
        candidates: List[Tuple[str, str]],  # (reasoning, answer) pairs
        threshold: float = 0.7
    ) -> List[Tuple[str, str]]:
        """
        Filter candidates by reasoning quality.

        Args:
            candidates: list of (reasoning_trace, answer) pairs
            threshold: minimum quality score

        Returns:
            filtered: high-quality candidates only
        """
        filtered = []
        for reasoning, answer in candidates:
            quality = self.calibrate_reasoning_quality("", reasoning)
            if quality >= threshold:
                filtered.append((reasoning, answer))
        return filtered
```

**Practical Application**

```python
def improved_factual_qa(
    question: str,
    model,
    knowledge_base,
    num_samples: int = 3,
    use_calibration: bool = True
) -> str:
    """
    Improved factual QA leveraging reasoning effects.

    Args:
        question: factual question
        model: language model
        knowledge_base: verified fact database
        num_samples: number of reasoning trajectories to generate
        use_calibration: whether to filter by reasoning quality

    Returns:
        answer: best answer considering reasoning quality
    """
    prompter = FactAwareReasoningPrompt(knowledge_base, model)
    calibrator = ReasoingCalibrationModule(model, knowledge_base)

    # Generate multiple reasoning trajectories
    prompt = prompter.construct_priming_prompt(question)

    candidates = []
    for _ in range(num_samples):
        # Generate with temperature for diversity
        reasoning = _generate_with_temperature(model, prompt, temperature=0.7)
        answer = extract_answer_from_reasoning(reasoning)
        candidates.append((reasoning, answer))

    if use_calibration:
        # Filter by reasoning quality
        high_quality = calibrator.filter_by_reasoning_quality(candidates, threshold=0.6)
        candidates = high_quality if high_quality else candidates

    # Return most common answer among candidates
    answers = [ans for _, ans in candidates]
    most_common = max(set(answers), key=answers.count)

    return most_common
```

## Practical Guidance

**Hyperparameters**:
- Reasoning length: 2-4 sentences works well; longer shows diminishing returns
- Fact priming count: 3 related facts optimal
- Verification threshold: 0.6-0.7 (allows some flexibility)
- Candidate generation: 3-5 samples for majority voting

**When to Apply**:
- Single-hop factual questions where baseline performance is poor
- Questions about well-covered topics in training data
- Scenarios where you can verify facts through external KB
- Improving calibration/confidence scores

**When NOT to Apply**:
- Multi-hop reasoning (standard chain-of-thought works)
- Questions about rare/recent facts
- No access to knowledge base for verification
- Real-time applications where reasoning adds latency

**Key Pitfalls**:
- Priming facts too different from question—doesn't help
- Verification against wrong KB—false confidence
- Reasoning trajectories too long—diminishing returns
- Not using multiple samples—single trajectory may be unlucky

**Integration Notes**: Works as a prompting strategy; requires knowledge base for fact verification; can be combined with retrieval-augmented generation for external fact access.

**Evidence**: Improves single-hop factual accuracy 5-15% through reasoning; computational buffering alone provides 2-3% improvement; fact verification enables proper calibration, reducing hallucination rates.

Reference: https://arxiv.org/abs/2603.09906

