Skip to content

[Bug] Automatic memory injection fails for Google GenAI provider (contents vs messages mismatch) #215

@TaiyakiVenturer

Description

@TaiyakiVenturer

First Check

  • I added a very descriptive title to this issue.
  • I searched existing issues and documentation.

Memori Version

3.0.6

OS / Python Version

Windows 10 / Python 3.13

LLM Provider

Gemini

LLM Model & Version

gemini-2.5-flash-lite

Database

SQLite

Description

I have encountered an issue where Memori successfully recalls facts from the database (verified via mem.recall()) but fails to inject them into the LLM's context when using the Google GenAI provider (e.g., gemini-2.5-flash or gemini-2.5-flash-lite ). The LLM responds as if it has no memory of the previous interactions.

Root Cause Analysis: Upon investigating memori/llm/_base.py, I identified two critical issues regarding how Google GenAI's contents parameter is handled:

  1. _extract_user_query ignores contents: The method currently only checks for kwargs["messages"]. Since Google GenAI SDK uses contents, it fails to extract the user's latest query from the arguments.

  2. inject_recalled_facts fails to update kwargs: In the else block (which handles providers other than Anthropic/Bedrock), the code retrieves a list using kwargs.get("messages", []).

else:
    messages = kwargs.get("messages", [])
    # ... (context is inserted into this local 'messages' list)
    messages.insert(0, context_message)
    # The modified 'messages' list is NEVER assigned back to kwargs['contents']

For Google GenAI, kwargs does not contain "messages". The get method returns a new, empty list. The code modifies this local list but never assigns it back to kwargs, let alone to the correct key kwargs["contents"]. As a result, the injected context is completely discarded before the API call.

Proposed Fix: I have implemented a fix locally that adds specific handling for llm_is_google in _base.py, which correctly injects the context into kwargs["contents"] (or kwargs["config"].system_instruction) and updates _extract_user_query to parse the contents structure. I am ready to submit a PR.

Minimal Reproducible Example

import os
from memori import Memori
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from google import genai
import time

# Ensure GOOGLE_API_KEY is set
# export GOOGLE_API_KEY="..."

def main():
    client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY"))
    
    # Setup local SQLite
    engine = create_engine("sqlite:///reproduce_issue.db")
    session = sessionmaker(bind=engine)

    # Register Google client
    mem = Memori(conn=session).google.register(client)
    
    # 1. Setup Identity
    entity_id = "TestUser_123"
    mem.attribution(entity_id=entity_id, process_id="test_process")
    mem.config.storage.build()

    # 2. Inject a fact manually (or via conversation)
    # "User likes playing Warframe"
    # Wait a bit to ensure it is written to DB
    print("Injecting fact...")
    # Note: Assuming this fact is already in DB or added here via a prior run
    # For reproduction, we can assume the DB has: "TestUser_123 likes Warframe"
    
    # 3. Verify Recall works (Debug)
    # This PROVES the memory exists and can be retrieved
    query = "Do you know what game I like?"
    print(f"Debug Recall Result: {mem.recall(query, entity_id=entity_id)}")
    # Expected output: [{'content': 'User likes Warframe', 'similarity': 0.7...}]

    # 4. Ask LLM (Stateless call)
    # Expected: LLM should answer "Warframe" if memory injection works.
    # Actual: LLM says "I don't know".
    print("\nAsking LLM...")
    response = client.models.generate_content(
        model="gemini-2.5-flash-lite",
        contents=query
    )
    print(f"LLM Response: {response.text}")

if __name__ == "__main__":
    main()

Log Output / Stack Trace

Debug Recall Result: [{'id': 1, 'content': 'TestUser_123 likes playing Warframe', 'similarity': 0.65}]

Asking LLM...
LLM Response: I'm sorry, I don't know what games you like yet. Could you tell me?

(Note: The log shows that mem.recall() successfully found the fact with high similarity, but the LLM response indicates it did not receive that context.)

Participation

  • I am willing to submit a pull request for this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions