A comprehensive benchmark for evaluating conversational memory in large language models, featuring 75,336 question-answer pairs across six evidence categories. This benchmark enables systematic evaluation of how well AI assistants remember and utilize information from previous conversations.
ConvoMem provides diverse test cases for evaluating conversational memory:
| Category | Description | Test Cases | Example |
|---|---|---|---|
| User Facts | User states facts, later asks assistant to recall | 16,733 | User: "I have 3 kids named Emma, Josh, and Lily" β Q: "How many children do I have?" β A: "3" |
| Assistant Facts | Assistant provides info, user asks to recall it | 12,745 | Assistant: "The team meeting is scheduled for 3pm in Conference Room B" β Q: "When did you say the meeting was?" β A: "3pm" |
| Changing Facts | Information evolves over conversation | 18,323 | "My budget is $5k" β "Actually, increase it to $7k" β "Wait, make it $10k" β Q: "What's my current budget?" β A: "$10k" |
| Abstention | Questions where no answer exists | 14,910 | Conversation about project timeline, no phone mentioned β Q: "What's John's phone number?" β A: "This wasn't mentioned in our conversation" |
| Preferences | User preferences for recommendations | 5,079 | User: "I prefer Python, value simplicity, dislike Java" β Q: "What backend framework should I use?" β A: "FastAPI or Flask (Python-based, simple)" |
| Implicit Connections | Multi-hop reasoning across messages | 7,546 | "Sarah manages the Sales team" + "Sales team uses Salesforce" β Q: "What CRM does Sarah's team use?" β A: "Salesforce" |
The benchmark tests both concentrated and distributed information:
This tests whether systems can synthesize scattered information, not just retrieve single facts.
The benchmark evaluation runs through Gradle (Java 17+ required). Results are saved to logs/[evidence_type]/[timestamp]/ with detailed metrics, costs, and per-question results.
# Set API keys
echo "GOOGLE_AI_API_KEY=your_gemini_key" > .env
# Run evaluation
./gradlew run --args="evaluate --type user_facts --memory long_context"
CRM_Mem_Bench/
βββ src/
β βββ main/
β β βββ scala/com/salesforce/crmmembench/
β β β βββ conversations/ # Conversation generation and loading
β β β β βββ ConversationGenerator.scala
β β β β βββ ConversationLoader.scala
β β β β βββ FillerConversationGenerator.scala
β β β β
β β β βββ evaluation/ # Evaluation framework
β β β β βββ Evaluator.scala # Base evaluator trait
β β β β βββ MultithreadedEvaluator.scala
β β β β βββ TestCasesGenerator.scala
β β β β βββ memory/ # Memory-specific evaluators
β β β β βββ Evaluate*UserFactsEvidence*.scala
β β β β βββ Evaluate*ChangingEvidence*.scala
β β β β βββ Evaluate*PreferenceEvidence*.scala
β β β β
β β β βββ LLM_endpoints/ # LLM integrations
β β β β βββ LLMClient.scala # Base LLM interface
β β β β βββ Gemini.scala # Google Gemini models
β β β β βββ GPT.scala # OpenAI GPT models
β β β β βββ Claude.scala # Anthropic Claude (not used)
β β β β
β β β βββ memory/ # Memory system implementations
β β β β βββ MemoryAnswerer.scala # Base trait
β β β β βββ LongContextMemoryAnswerer.scala
β β β β βββ BlockExtractedContextAnswerer.scala
β β β β βββ mem0/
β β β β βββ Mem0MemoryAnswerer.scala
β β β β
β β β βββ personas/ # Persona management
β β β β βββ PersonaManager.scala
β β β β
β β β βββ questions/ # Question/evidence generation
β β β β βββ evidence/
β β β β βββ EvidenceGenerator.scala # Base trait
β β β β βββ UserFactsEvidenceGenerator.scala
β β β β βββ ChangingEvidenceGenerator.scala
β β β β βββ PreferenceEvidenceGenerator.scala
β β β β βββ generators/ # Specific implementations
β β β β
β β β βββ test/ # Test runners
β β β βββ TestRunner.scala
β β β βββ TestUtils.scala
β β β
β β βββ resources/
β β βββ personas/ # Generated persona files
β β βββ evidence/ # Generated evidence Q&A pairs
β β βββ conversations/ # Generated conversations
β β βββ test_cases/ # Cached test cases (gitignored)
β β
β βββ test/ # Unit tests
β βββ scala/com/salesforce/crmmembench/
β βββ conversations/*Test.scala
β βββ evaluation/*Test.scala
β βββ questions/*Test.scala
β
βββ logs/ # Evaluation results (gitignored)
β βββ [evidence_type]/[timestamp]/
β βββ results.json # Detailed results
β βββ summary.txt # Accuracy by context size
β βββ costs.csv # Token usage and costs
β
βββ build.gradle # Gradle build configuration
βββ gradle.properties # Gradle settings
βββ README.md # This file
You can access the benchmark dataset in two ways:
From Hugging Face: Download the pre-generated dataset with 75,336 question-answer pairs at huggingface.co/datasets/Salesforce/ConvoMem
From This Repository: Generate or load the dataset using the Scala evaluation framework:
import com.salesforce.crmmembench.questions.evidence.generators.UserFactsEvidenceGenerator
import com.salesforce.crmmembench.evaluation.{ConversationLoader, TestCasesGenerator}
// Create evidence generator with 3 facts to track
val evidenceGenerator = new UserFactsEvidenceGenerator(3)
// Load evidence items from resources
val evidenceItems = evidenceGenerator.loadEvidenceItems()
// Load irrelevant conversations for mixing
val irrelevantConversations = ConversationLoader.loadIrrelevantConversations()
// Create test cases with standard mixing strategy
val testCasesGen = TestCasesGenerator.createStandard(evidenceGenerator)
val testCases = testCasesGen.generateTestCases()
The benchmark creates realistic memory challenges through a sophisticated multi-stage pipeline:
Purpose: Create diverse, realistic user profiles to ensure variety in conversations
Process: Generate 100 personas spanning different roles (sales, marketing, engineering, etc.) with rich backgrounds including work history, communication style, and domain expertise
Main Class: PersonaGeneration.scala - Orchestrates persona creation and enrichment
Validation: Check for diversity across roles, ensure no duplicate names, verify each persona has complete biographical information
Purpose: Add depth and nuance to make conversations authentic
Process: Each persona receives additional details like specific tool preferences, industry jargon, and personal quirks that make their conversations unique
Main Class: PersonaEnricher.scala - Adds biographical details and conversational traits
Validation: Verify enrichment details are consistent with base persona (e.g., a sales director shouldn't have engineering tools as preferences), ensure no contradictions in biographical details
Purpose: Define realistic scenarios where memory matters
Process: For each persona, generate 50-100 scenarios in a single LLM call. This batching is crucial for diversity - the model can see all previously generated scenarios within the batch and ensure each explores different aspects of the persona's life, avoiding repetition and maximizing coverage
Main Classes: UseCaseGenerator.scala - Creates scenario descriptions and contexts
Validation: Check that each scenario includes a clear question, verify scenarios are appropriate for the persona's role and background, ensure diversity across scenarios (no repetitive patterns)
Purpose: Create the actual question-answer pairs with supporting evidence Process: Transform use cases into concrete Q&A pairs with evidence messages that must appear in conversations. Process each scenario individually for quality focus Main Classes:
EvidenceGenerator.scala - Base trait for all evidence generationUserFactsEvidenceGenerator.scala - Generates user-stated factsChangingEvidenceGenerator.scala - Creates evolving information
Validation:Purpose: Embed evidence naturally within realistic dialogue Process: Generate 100-message conversations where evidence appears organically. The conversation flows naturally around the topic without making the evidence obvious Main Classes:
ConversationGenerator.scala - Creates natural dialogue flowsConversationEmbedder.scala - Places evidence within conversations
Validation:Purpose: Mix evidence conversations with irrelevant ones at varying scales Process: Combine evidence-containing conversations with filler conversations to create test cases with 2 to 300 total conversations Main Classes:
TestCasesGenerator.scala - Orchestrates test case creationStandardTestCasesGenerator.scala - Default mixing strategyConversationLoader.scala - Loads filler conversations
Validation:Purpose: Test memory systems and measure performance Process: Load conversations into memory systems, ask questions, measure accuracy/cost/latency Main Classes:
MultithreadedEvaluator.scala - Runs parallel evaluationsMemoryAnswerer.scala - Interface for memory systemsStatsReporter.scala - Generates performance reportsAs conversations accumulate, finding relevant information becomes increasingly difficult:
The benchmark measures how accuracy degrades as this "haystack" grows larger.
Each evidence type tests a different cognitive capability:
To integrate your own memory system, implement the MemoryAnswerer trait. Your system needs to:
The framework handles the rest: loading test cases, measuring accuracy, tracking costs, and generating reports.
The repository includes pre-built evaluators for each evidence type. These can be run directly from IntelliJ IDEA or via Gradle. Each evaluator:
logs/ for analysisEvidence counts range from 1 (single fact) to 6 (multiple facts to track), testing increasingly complex memory requirements.
The benchmark uses a modular architecture for creating test cases:
Evidence Generators - Create question-answer pairs with conversation context
UserFactsEvidenceGenerator - Facts stated by usersChangingEvidenceGenerator - Information that evolves over timePreferenceEvidenceGenerator - User preferences and recommendationsTest Case Generators - Mix evidence with irrelevant conversations
StandardTestCasesGenerator - Tests each evidence item individually with varying context sizesBatchedTestCasesGenerator - Groups multiple evidence items for efficiencyMemory Answerers - Different approaches to answering questions
LongContextMemoryAnswerer - Puts entire conversation history in contextBlockExtractedContextAnswerer - Processes conversations in blocks, extracts relevant infoMem0MemoryAnswerer - Uses external RAG-based memory serviceEdit src/main/scala/com/salesforce/crmmembench/Config.scala:
object Config {
val DEBUG = false // Verbose logging
val CONTEXT_SIZES = List(2, 4, 6, 10, 20, 30, 50, 70, 100, 150, 200, 300)
val EVALUATION_THREADS = 40
val USE_CACHED_TEST_CASES = true // Use pre-generated test cases
}
The benchmark supports multiple evaluation metrics:
We welcome contributions! Areas of interest include:
See CONTRIBUTING.md for guidelines.
@article{convomem2025,
title={ConvoMem: A Comprehensive Benchmark for Conversational Memory},
author={[Authors]},
year={2025}
}
Apache License 2.0 - see LICENSE file.
Built by Salesforce AI Research
A comprehensive benchmark for evaluating conversational memory in large language models, featuring 75,336 question-answer pairs across six evidence categories. This benchmark enables systematic evaluation of how well AI assistants remember and utilize information from previous conversations.
ConvoMem provides diverse test cases for evaluating conversational memory:
| Category | Description | Test Cases | Example |
|---|---|---|---|
| User Facts | User states facts, later asks assistant to recall | 16,733 | User: "I have 3 kids named Emma, Josh, and Lily" β Q: "How many children do I have?" β A: "3" |
| Assistant Facts | Assistant provides info, user asks to recall it | 12,745 | Assistant: "The team meeting is scheduled for 3pm in Conference Room B" β Q: "When did you say the meeting was?" β A: "3pm" |
| Changing Facts | Information evolves over conversation | 18,323 | "My budget is $5k" β "Actually, increase it to $7k" β "Wait, make it $10k" β Q: "What's my current budget?" β A: "$10k" |
| Abstention | Questions where no answer exists | 14,910 | Conversation about project timeline, no phone mentioned β Q: "What's John's phone number?" β A: "This wasn't mentioned in our conversation" |
| Preferences | User preferences for recommendations | 5,079 | User: "I prefer Python, value simplicity, dislike Java" β Q: "What backend framework should I use?" β A: "FastAPI or Flask (Python-based, simple)" |
| Implicit Connections | Multi-hop reasoning across messages | 7,546 | "Sarah manages the Sales team" + "Sales team uses Salesforce" β Q: "What CRM does Sarah's team use?" β A: "Salesforce" |
The benchmark tests both concentrated and distributed information:
This tests whether systems can synthesize scattered information, not just retrieve single facts.
The benchmark evaluation runs through Gradle (Java 17+ required). Results are saved to logs/[evidence_type]/[timestamp]/ with detailed metrics, costs, and per-question results.
# Set API keys
echo "GOOGLE_AI_API_KEY=your_gemini_key" > .env
# Run evaluation
./gradlew run --args="evaluate --type user_facts --memory long_context"
CRM_Mem_Bench/
βββ src/
β βββ main/
β β βββ scala/com/salesforce/crmmembench/
β β β βββ conversations/ # Conversation generation and loading
β β β β βββ ConversationGenerator.scala
β β β β βββ ConversationLoader.scala
β β β β βββ FillerConversationGenerator.scala
β β β β
β β β βββ evaluation/ # Evaluation framework
β β β β βββ Evaluator.scala # Base evaluator trait
β β β β βββ MultithreadedEvaluator.scala
β β β β βββ TestCasesGenerator.scala
β β β β βββ memory/ # Memory-specific evaluators
β β β β βββ Evaluate*UserFactsEvidence*.scala
β β β β βββ Evaluate*ChangingEvidence*.scala
β β β β βββ Evaluate*PreferenceEvidence*.scala
β β β β
β β β βββ LLM_endpoints/ # LLM integrations
β β β β βββ LLMClient.scala # Base LLM interface
β β β β βββ Gemini.scala # Google Gemini models
β β β β βββ GPT.scala # OpenAI GPT models
β β β β βββ Claude.scala # Anthropic Claude (not used)
β β β β
β β β βββ memory/ # Memory system implementations
β β β β βββ MemoryAnswerer.scala # Base trait
β β β β βββ LongContextMemoryAnswerer.scala
β β β β βββ BlockExtractedContextAnswerer.scala
β β β β βββ mem0/
β β β β βββ Mem0MemoryAnswerer.scala
β β β β
β β β βββ personas/ # Persona management
β β β β βββ PersonaManager.scala
β β β β
β β β βββ questions/ # Question/evidence generation
β β β β βββ evidence/
β β β β βββ EvidenceGenerator.scala # Base trait
β β β β βββ UserFactsEvidenceGenerator.scala
β β β β βββ ChangingEvidenceGenerator.scala
β β β β βββ PreferenceEvidenceGenerator.scala
β β β β βββ generators/ # Specific implementations
β β β β
β β β βββ test/ # Test runners
β β β βββ TestRunner.scala
β β β βββ TestUtils.scala
β β β
β β βββ resources/
β β βββ personas/ # Generated persona files
β β βββ evidence/ # Generated evidence Q&A pairs
β β βββ conversations/ # Generated conversations
β β βββ test_cases/ # Cached test cases (gitignored)
β β
β βββ test/ # Unit tests
β βββ scala/com/salesforce/crmmembench/
β βββ conversations/*Test.scala
β βββ evaluation/*Test.scala
β βββ questions/*Test.scala
β
βββ logs/ # Evaluation results (gitignored)
β βββ [evidence_type]/[timestamp]/
β βββ results.json # Detailed results
β βββ summary.txt # Accuracy by context size
β βββ costs.csv # Token usage and costs
β
βββ build.gradle # Gradle build configuration
βββ gradle.properties # Gradle settings
βββ README.md # This file
You can access the benchmark dataset in two ways:
From Hugging Face: Download the pre-generated dataset with 75,336 question-answer pairs at huggingface.co/datasets/Salesforce/ConvoMem
From This Repository: Generate or load the dataset using the Scala evaluation framework:
import com.salesforce.crmmembench.questions.evidence.generators.UserFactsEvidenceGenerator
import com.salesforce.crmmembench.evaluation.{ConversationLoader, TestCasesGenerator}
// Create evidence generator with 3 facts to track
val evidenceGenerator = new UserFactsEvidenceGenerator(3)
// Load evidence items from resources
val evidenceItems = evidenceGenerator.loadEvidenceItems()
// Load irrelevant conversations for mixing
val irrelevantConversations = ConversationLoader.loadIrrelevantConversations()
// Create test cases with standard mixing strategy
val testCasesGen = TestCasesGenerator.createStandard(evidenceGenerator)
val testCases = testCasesGen.generateTestCases()
The benchmark creates realistic memory challenges through a sophisticated multi-stage pipeline:
Purpose: Create diverse, realistic user profiles to ensure variety in conversations
Process: Generate 100 personas spanning different roles (sales, marketing, engineering, etc.) with rich backgrounds including work history, communication style, and domain expertise
Main Class: PersonaGeneration.scala - Orchestrates persona creation and enrichment
Validation: Check for diversity across roles, ensure no duplicate names, verify each persona has complete biographical information
Purpose: Add depth and nuance to make conversations authentic
Process: Each persona receives additional details like specific tool preferences, industry jargon, and personal quirks that make their conversations unique
Main Class: PersonaEnricher.scala - Adds biographical details and conversational traits
Validation: Verify enrichment details are consistent with base persona (e.g., a sales director shouldn't have engineering tools as preferences), ensure no contradictions in biographical details
Purpose: Define realistic scenarios where memory matters
Process: For each persona, generate 50-100 scenarios in a single LLM call. This batching is crucial for diversity - the model can see all previously generated scenarios within the batch and ensure each explores different aspects of the persona's life, avoiding repetition and maximizing coverage
Main Classes: UseCaseGenerator.scala - Creates scenario descriptions and contexts
Validation: Check that each scenario includes a clear question, verify scenarios are appropriate for the persona's role and background, ensure diversity across scenarios (no repetitive patterns)
Purpose: Create the actual question-answer pairs with supporting evidence Process: Transform use cases into concrete Q&A pairs with evidence messages that must appear in conversations. Process each scenario individually for quality focus Main Classes:
EvidenceGenerator.scala - Base trait for all evidence generationUserFactsEvidenceGenerator.scala - Generates user-stated factsChangingEvidenceGenerator.scala - Creates evolving information
Validation:Purpose: Embed evidence naturally within realistic dialogue Process: Generate 100-message conversations where evidence appears organically. The conversation flows naturally around the topic without making the evidence obvious Main Classes:
ConversationGenerator.scala - Creates natural dialogue flowsConversationEmbedder.scala - Places evidence within conversations
Validation:Purpose: Mix evidence conversations with irrelevant ones at varying scales Process: Combine evidence-containing conversations with filler conversations to create test cases with 2 to 300 total conversations Main Classes:
TestCasesGenerator.scala - Orchestrates test case creationStandardTestCasesGenerator.scala - Default mixing strategyConversationLoader.scala - Loads filler conversations
Validation:Purpose: Test memory systems and measure performance Process: Load conversations into memory systems, ask questions, measure accuracy/cost/latency Main Classes:
MultithreadedEvaluator.scala - Runs parallel evaluationsMemoryAnswerer.scala - Interface for memory systemsStatsReporter.scala - Generates performance reportsAs conversations accumulate, finding relevant information becomes increasingly difficult:
The benchmark measures how accuracy degrades as this "haystack" grows larger.
Each evidence type tests a different cognitive capability:
To integrate your own memory system, implement the MemoryAnswerer trait. Your system needs to:
The framework handles the rest: loading test cases, measuring accuracy, tracking costs, and generating reports.
The repository includes pre-built evaluators for each evidence type. These can be run directly from IntelliJ IDEA or via Gradle. Each evaluator:
logs/ for analysisEvidence counts range from 1 (single fact) to 6 (multiple facts to track), testing increasingly complex memory requirements.
The benchmark uses a modular architecture for creating test cases:
Evidence Generators - Create question-answer pairs with conversation context
UserFactsEvidenceGenerator - Facts stated by usersChangingEvidenceGenerator - Information that evolves over timePreferenceEvidenceGenerator - User preferences and recommendationsTest Case Generators - Mix evidence with irrelevant conversations
StandardTestCasesGenerator - Tests each evidence item individually with varying context sizesBatchedTestCasesGenerator - Groups multiple evidence items for efficiencyMemory Answerers - Different approaches to answering questions
LongContextMemoryAnswerer - Puts entire conversation history in contextBlockExtractedContextAnswerer - Processes conversations in blocks, extracts relevant infoMem0MemoryAnswerer - Uses external RAG-based memory serviceEdit src/main/scala/com/salesforce/crmmembench/Config.scala:
object Config {
val DEBUG = false // Verbose logging
val CONTEXT_SIZES = List(2, 4, 6, 10, 20, 30, 50, 70, 100, 150, 200, 300)
val EVALUATION_THREADS = 40
val USE_CACHED_TEST_CASES = true // Use pre-generated test cases
}
The benchmark supports multiple evaluation metrics:
We welcome contributions! Areas of interest include:
See CONTRIBUTING.md for guidelines.
@article{convomem2025,
title={ConvoMem: A Comprehensive Benchmark for Conversational Memory},
author={[Authors]},
year={2025}
}
Apache License 2.0 - see LICENSE file.
Built by Salesforce AI Research