feat: use main agent LLM for memory extraction instead of mem0's GPT-nano
Build Nanobot OAuth / build (pull_request) Successful in 6m28s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped

Instead of hacking mem0's provider system to swap GPT-nano for Haiku,
use the main agent's existing LLM provider (already running, already paid for)
to extract facts from conversations, then store them with infer=False.

Changes to memory_mem0.py:
- extract_facts(): uses provider/model from consolidate() to extract facts
- store_facts(): stores pre-extracted facts with mem0 infer=False
- consolidate(): calls extract_facts + store_facts instead of add_conversation
- Saves custom_prompt as instance variable for extract_facts to use

Removed:
- mem0_anthropic_oauth.py (no longer needed)
- Dockerfile sed patch (no longer needed)

No changes to mem0 package files. No new dependencies.
This commit is contained in:
2026-03-04 01:48:37 +01:00
parent 3126b99fdb
commit 99bd54a162
+94 -6
View File
@@ -147,6 +147,7 @@ Here is the conversation to extract facts from:
if key in raw_config:
mem0_cfg_dict[key] = raw_config[key]
logger.debug(f"Extracted for MemoryConfig: {list(mem0_cfg_dict.keys())}")
self.custom_prompt = custom_prompt
mem0_cfg_dict["custom_fact_extraction_prompt"] = custom_prompt
mem0_config = MemoryConfig(**mem0_cfg_dict)
logger.debug(f"MemoryConfig created: vector_store={mem0_config.vector_store.provider if mem0_config.vector_store else None}")
@@ -238,6 +239,95 @@ Here is the conversation to extract facts from:
except Exception as e:
logger.error(f"Mem0 add failed: {e}")
async def extract_facts(
self,
messages: list[dict[str, Any]],
provider: "LLMProvider",
model: str,
) -> list[str]:
"""
Extract facts from conversation using the main agent's LLM provider.
Uses the same provider/model already running (e.g. Haiku via Claude Max),
avoiding a separate LLM call to mem0's default GPT-nano.
"""
import json as _json
# Build conversation text for extraction
conv_text = ""
for msg in messages:
role = msg.get("role", "unknown")
content = msg.get("content", "")
if isinstance(content, str) and content.strip():
conv_text += f"{role}: {content}\n\n"
if not conv_text.strip():
return []
extraction_messages = [
{"role": "user", "content": self.custom_prompt + conv_text}
]
try:
response = await provider.create_message(
model=model,
max_tokens=2000,
messages=extraction_messages,
)
# Parse the JSON response
text = response.content[0].text if response.content else ""
# Strip markdown code fences if present
text = text.strip()
if text.startswith("```"):
text = text.split("\n", 1)[1] if "\n" in text else text[3:]
if text.endswith("```"):
text = text[:-3]
text = text.strip()
data = _json.loads(text)
facts = data.get("facts", [])
logger.debug(f"Extracted {len(facts)} facts using {model}")
return facts
except Exception as e:
logger.error(f"Fact extraction failed: {e}")
return []
def store_facts(
self,
facts: list[str],
user_id: str,
session_id: str | None = None,
) -> None:
"""
Store pre-extracted facts in mem0 with infer=False.
Bypasses mem0's built-in LLM extraction — facts are already
in final form from extract_facts().
"""
if not facts:
return
metadata = {}
if session_id:
metadata["session_id"] = session_id
stored = 0
for fact in facts:
try:
self.memory.add(
fact,
user_id=user_id,
infer=False,
metadata=metadata if metadata else None,
)
stored += 1
except Exception as e:
logger.error(f"Failed to store fact '{fact[:50]}...': {e}")
logger.info(f"Stored {stored}/{len(facts)} facts for user {user_id}")
def get_memory_context(
self,
query: str,
@@ -407,12 +497,10 @@ Here is the conversation to extract facts from:
})
if mem0_messages:
# Add to mem0 - it handles extraction automatically
self.add_conversation(
mem0_messages,
user_id=user_id,
session_id=session.key
)
# Extract facts using the main agent's LLM (already paid for),
# then store with infer=False to bypass mem0's GPT-nano
facts = await self.extract_facts(mem0_messages, provider, model)
self.store_facts(facts, user_id=user_id, session_id=session.key)
# Update consolidation marker
if archive_all: