mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-04-30 14:52:36 +00:00
refactor: update MemoryPromptConfig to allow custom prompt strings
* Removed the static method for online people research and replaced it with a constructor for MemoryPromptConfig that accepts custom strings for save, extract, and query systems. * Updated the corresponding test to validate the new configuration approach, ensuring flexibility in memory prompt handling.
This commit is contained in:
@@ -153,104 +153,6 @@ class MemoryPromptConfig(BaseModel):
|
||||
consolidation_system: str | None = None
|
||||
consolidation_user: str | None = None
|
||||
|
||||
@classmethod
|
||||
def for_online_people_research(cls) -> MemoryPromptConfig:
|
||||
"""Prompt profile for open-web people research (e.g. Exa).
|
||||
|
||||
Biases memory toward **search provenance** (queries, domains, URLs, dead
|
||||
ends, strong sources) and away from storing fragile biographical detail
|
||||
or speculation as high-confidence fact. Pair with ``EXASearchTool`` and
|
||||
explicit scopes/categories in ``remember()`` when you need determinism.
|
||||
"""
|
||||
return cls(
|
||||
save_system=(
|
||||
"You analyze content for a hierarchical memory used during "
|
||||
"online people research.\n"
|
||||
"Prioritize durable *research-process* signals over raw biographical claims:\n"
|
||||
"- suggested_scope: use paths like /subjects/<slug>, /searches/queries, "
|
||||
"/sources/domains when the content is about where or how you searched.\n"
|
||||
"- categories: include tags such as search_query, result_domain, "
|
||||
"source_url, exa_search, dead_end, preferred_source, methodology "
|
||||
"when applicable. Use subject_profile only for well-sourced factual "
|
||||
"snippets tied to a named URL or document - not for gossip or guesses.\n"
|
||||
"- importance: higher (0.7-1.0) for reusable search lessons "
|
||||
"(e.g. 'site X returned 404', 'LinkedIn useful for role Y', "
|
||||
"'query phrasing Z worked'). Lower (0.2-0.5) for one-off personal "
|
||||
"minutiae or unverified claims.\n"
|
||||
"- extracted_metadata.entities: prefer domains, publication names, "
|
||||
"and search keywords; only list people when the text explicitly "
|
||||
"anchors a fact to a source.\n"
|
||||
"Given the content and existing scopes and categories, output:\n"
|
||||
"1. suggested_scope\n2. categories\n3. importance\n4. extracted_metadata"
|
||||
),
|
||||
save_user=(
|
||||
"Content to store:\n{content}\n\n"
|
||||
"Existing scopes: {existing_scopes}\n"
|
||||
"Existing categories: {existing_categories}\n\n"
|
||||
"Return the analysis as structured output."
|
||||
),
|
||||
query_system=(
|
||||
"You analyze a query against memory for people-research crews.\n"
|
||||
"Favor recalling *how and where* the team already searched:\n"
|
||||
"- keywords: include domains, site names, query stems, and subject "
|
||||
"handles - not only the person's name.\n"
|
||||
"- suggested_scopes: prefer /searches, /sources, /subjects as relevant.\n"
|
||||
"- recall_queries: produce phrases that would match memories about "
|
||||
"Exa queries, domains tried, and conclusions about source quality.\n"
|
||||
"- complexity: 'complex' if the question asks to synthesize many sources; "
|
||||
"else 'simple'.\n"
|
||||
"- time_filter: ISO date if the query implies a time window; else null.\n"
|
||||
"Given the query and available scopes, output:\n"
|
||||
"1. keywords\n2. suggested_scopes\n3. complexity\n4. recall_queries\n"
|
||||
"5. time_filter"
|
||||
),
|
||||
query_user=(
|
||||
"Query: {query}\n\n"
|
||||
"Available scopes: {available_scopes}\n"
|
||||
"{scope_desc}\n\n"
|
||||
"Return the analysis as structured output."
|
||||
),
|
||||
extract_memories_system=(
|
||||
"Extract discrete memory statements from research logs (tool outputs, "
|
||||
"Exa results, agent notes).\n"
|
||||
"HIGH priority - always capture when present:\n"
|
||||
"- Exact or paraphrased search queries used and which engine/tool "
|
||||
"(e.g. Exa).\n"
|
||||
"- Domains and canonical URLs of pages opened; HTTP errors or empty results.\n"
|
||||
"- Judgments about source usefulness (e.g. 'official bio on company site', "
|
||||
"'social profile - verify elsewhere').\n"
|
||||
"MEDIUM priority:\n"
|
||||
"- Verifiable facts explicitly tied to a source in the text "
|
||||
"(quote which source).\n"
|
||||
"LOW priority / often skip:\n"
|
||||
"- Speculation, reputation gossip, or detailed private life unless "
|
||||
"the task explicitly requires it and a primary source is named.\n"
|
||||
"Each memory: one clear sentence, no duplicate ideas.\n"
|
||||
'Output JSON with a single key "memories" whose value is a list of strings.'
|
||||
),
|
||||
extract_memories_user=(
|
||||
"Content:\n{content}\n\n"
|
||||
"Extract memory statements as described. Return structured output."
|
||||
),
|
||||
consolidation_system=(
|
||||
"You consolidate new research content with similar existing memories.\n"
|
||||
"Prefer keeping separate memories when they differ by URL, domain, or "
|
||||
"search query - even if about the same person.\n"
|
||||
"Merge or update when the new text clearly refines the same source "
|
||||
"or same search finding.\n"
|
||||
"Delete only when a memory is clearly wrong and superseded.\n"
|
||||
"Be conservative: prefer 'keep' when unsure.\n"
|
||||
"For each existing memory: keep | update | delete. "
|
||||
"Set insert_new when the new content adds a distinct query, URL, or "
|
||||
"source judgment."
|
||||
),
|
||||
consolidation_user=(
|
||||
"New content to consider storing:\n{new_content}\n\n"
|
||||
"Existing similar memories:\n{records_summary}\n\n"
|
||||
"Return the consolidation plan as structured output."
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class MemoryConfig(BaseModel):
|
||||
"""Internal configuration for memory scoring, consolidation, and recall behavior.
|
||||
|
||||
@@ -653,13 +653,18 @@ def test_remember_survives_llm_failure(
|
||||
# --- Per-Memory prompt config (MemoryPromptConfig) ---
|
||||
|
||||
|
||||
def test_memory_prompt_overrides_for_online_people_research() -> None:
|
||||
def test_memory_prompt_config_custom_strings() -> None:
|
||||
"""Library stays domain-agnostic; apps pass their own MemoryPromptConfig."""
|
||||
from crewai.memory.types import MemoryPromptConfig
|
||||
|
||||
po = MemoryPromptConfig.for_online_people_research()
|
||||
assert po.save_system and "search_query" in po.save_system
|
||||
assert po.extract_memories_system and "Exa" in po.extract_memories_system
|
||||
assert po.query_system and "recall_queries" in po.query_system
|
||||
po = MemoryPromptConfig(
|
||||
save_system="Prefer categories: search_query, exa_search, result_domain.",
|
||||
extract_memories_system="Record Exa queries and canonical URLs first.",
|
||||
query_system="Distill recall_queries toward domains and past queries.",
|
||||
)
|
||||
assert "search_query" in (po.save_system or "")
|
||||
assert "Exa" in (po.extract_memories_system or "")
|
||||
assert "recall_queries" in (po.query_system or "")
|
||||
|
||||
|
||||
def test_memory_prompt_overrides_save_system_used_in_analyze(tmp_path: Path) -> None:
|
||||
|
||||
Reference in New Issue
Block a user