Skip to main content

Memory module for creating intelligent agents within Microsoft Teams

Project description

[!IMPORTANT]
teams_memory is in alpha. We are still internally validating and testing!

Teams Memory Module

The Teams Memory Module is a simple yet powerful library designed to help manage memories for Teams AI Agents. By offloading the responsibility of tracking user-related facts, it enables developers to create more personable and efficient agents.

Features

  • Seamless Integration with Teams AI SDK:
    The memory module integrates directly with the Teams AI SDK via middleware, tracking both incoming and outgoing messages.

  • Automatic Memory Extraction:
    Define a set of topics (or use default ones) relevant to your application, and the memory module will automatically extract and store related memories.

  • Simple Short-Term Memory Retrieval:
    Easily retrieve working memory using paradigms like "last N minutes" or "last M messages."

  • Query-Based or Topic-Based Memory Retrieval:
    Search for existing memories using natural language queries or predefined topics.

Integration

Integrating the Memory Module into your Teams AI SDK application (or Bot Framework) is straightforward.

Prerequisites

  • Azure OpenAI or OpenAI Keys:
    The LLM layer is built using LiteLLM, which supports multiple providers. However, only Azure OpenAI (AOAI) and OpenAI (OAI) have been tested.

Integrating into a Teams AI SDK Application

Adding Messages

Incoming / Outgoing Messages

Memory extraction requires incoming and outgoing messages to your application. To simplify this, you can use middleware to automate the process.

After building your bot Application, create a MemoryMiddleware with the following configurations:

  • llm: Configuration for the LLM (required).
  • storage: Configuration for the storage layer. Defaults to InMemoryStorage if not provided.
  • buffer_size: Minimum size of the message buffer before memory extraction is triggered.
  • timeout_seconds: Time elapsed after the buffer starts filling up before extraction occurs.
    • Note: Extraction occurs when either the buffer_size is reached or the timeout_seconds elapses, whichever happens first.
  • topics: Topics relevant to your application. These help the LLM focus on important information and avoid unnecessary extractions.
memory_middleware = MemoryMiddleware(
    config=MemoryModuleConfig(
        llm=LLMConfig(**memory_llm_config),
        storage=StorageConfig(
            db_path=os.path.join(os.path.dirname(__file__), "data", "memory.db")
        ),  # Uses SQLite if `db_path` is provided
        timeout_seconds=60,  # Extraction occurs 60 seconds after the first message
        enable_logging=True,  # Helpful for debugging
        topics=[
            Topic(name="Device Type", description="The type of device the user has"),
            Topic(name="Operating System", description="The operating system for the user's device"),
            Topic(name="Device Year", description="The year of the user's device"),
        ],  # Example topics for a tech-assistant agent
    )
)
bot_app.adapter.use(memory_middleware)

At this point, the application automatically listens to all incoming and outgoing messages.

[!TIP]
This integration augments the TurnContext with a memory_module property, scoped to the conversation for the request. Access it via:

memory_module: BaseScopedMemoryModule = context.get("memory_module")

[Optional] Internal Messages

The previous step only stores incoming and outgoing messages. You also have the option to o store InternalMessage objects (e.g., for additional context or tracking internal conversation states) via:

async def add_internal_message(self, context: TurnContext, tool_call_name: str, tool_call_result: str):
    conversation_ref_dict = TurnContext.get_conversation_reference(context.activity)
    memory_module: BaseScopedMemoryModule = context.get("memory_module")
    await memory_module.add_message(
        InternalMessageInput(
            content=json.dumps({"tool_call_name": tool_call_name, "result": tool_call_result}),
            author_id=conversation_ref_dict.bot.id,
            conversation_ref=memory_module.conversation_ref,
        )
    )
    return True

Extracting Memories

[!NOTE]
The memory module currently supports extracting semantic memories about a user. Future updates will include support for conversation-level memories. See Future Work for details.

There are two ways to extract memories:

  1. Automatic Extraction: Memories are extracted when the buffer_size is reached or the timeout_seconds elapses.
  2. On-Demand Extraction: Manually trigger extraction by calling memory_module.process_messages().

Automatic Extraction

Enable automatic extraction by calling memory_middleware.memory_module.listen() when your application starts. This listens to messages and triggers extraction based on the configured conditions.

async def initialize_memory_module(_app: web.Application):
    await memory_middleware.memory_module.listen()

async def shutdown_memory_module(_app: web.Application):
    await memory_middleware.memory_module.shutdown()

app.on_startup.append(initialize_memory_module)
app.on_shutdown.append(shutdown_memory_module)

web.run_app(app, host="localhost", port=Config.PORT)

[!IMPORTANT]
When performing automatic extraction via listen(), it's important to ensure that you also configure your application to cleanup resources when the application shuts down using the shutdown() method.

On-Demand Extraction

Use on-demand extraction to trigger memory extraction at specific points, such as after a tool_call or a particular message.

async def extract_memories_after_tool_call(context: TurnContext):
    memory_module: ScopedMemoryModule = context.get('memory_module')
    await memory_module.process_messages()  # Extracts memories from the buffer

[!NOTE]
memory_module.process_messages() can be called at any time, even if automatic extraction is enabled.

Using Short-Term Memories (Working Memory)

The memory module simplifies the retrieval of recent messages for use as context in your LLM.

async def build_llm_messages(self, context: TurnContext, system_message: str):
    memory_module: BaseScopedMemoryModule = context.get("memory_module")
    assert memory_module
    messages = await memory_module.retrieve_chat_history(
        ShortTermMemoryRetrievalConfig(last_minutes=1)
    )
    llm_messages: List = [
        {"role": "system", "content": system_prompt},
        *[
            {"role": "user" if message.type == "user" else "assistant", "content": message.content}
            for message in messages
        ],  # UserMessages have a `role` of `user`; others are `assistant`
    ]
    return llm_messages

Using Extracted Semantic Memory

Access extracted memories via the ScopedMemoryModule available in the TurnContext:

async def retrieve_device_type_memories(context: TurnContext):
    memory_module: ScopedMemoryModule = context.get('memory_module')
    device_type_memories = await memory_module.search_memories(
        topic="Device Type", # This name must match the topic name in the config
        query="What device does the user own?"
    )

You can search for memories using a topic, a natural language query, or both.

Logging

Enable logging in the memory module configuration:

config = MemoryModuleConfig()
config.enable_logging = True

The module uses Python's logging library. By default, it logs debug messages (and higher severity) to the console. Customize the logging behavior as follows:

from teams_memory import configure_logging

configure_logging(logging_level=logging.INFO)

Model Performance

Model Embedding Model Tested Notes
gpt-4o text-embedding-3-small Tested via both OpenAI and Azure OpenAI

Future Work

The Teams Memory Module is in active development. Planned features include:

  • Evals and Performance Testing: Support for additional models.
  • More Storage Providers: Integration with PostgreSQL, CosmosDB, etc.
  • Automatic Message Expiration: Delete messages older than a specified duration (e.g., 1 day).
  • Episodic Memory Extraction: Memories about conversations, not just users.
  • Sophisticated Memory Access Patterns: Secure sharing of memories across multiple groups.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

teams_memory-0.1.1a0.tar.gz (36.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

teams_memory-0.1.1a0-py3-none-any.whl (52.7 kB view details)

Uploaded Python 3

File details

Details for the file teams_memory-0.1.1a0.tar.gz.

File metadata

  • Download URL: teams_memory-0.1.1a0.tar.gz
  • Upload date:
  • Size: 36.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.16

File hashes

Hashes for teams_memory-0.1.1a0.tar.gz
Algorithm Hash digest
SHA256 3bfe26467f1f42761b85fce4121e6529b707783849e926434d9e193782ac028b
MD5 9d213fc2c5240c9cf2e2a795427613f8
BLAKE2b-256 aa3b496f9b777efa762793bb31a2706fd62d54e05fbcac6dbb9ea71fa1bb5b7c

See more details on using hashes here.

File details

Details for the file teams_memory-0.1.1a0-py3-none-any.whl.

File metadata

File hashes

Hashes for teams_memory-0.1.1a0-py3-none-any.whl
Algorithm Hash digest
SHA256 21ce433f30d5d89e6013187535abb04bc3b3292c3a0e2b8cbfa3d5d2d22963f0
MD5 05f3f917ed9ea5221839fc350809e7ea
BLAKE2b-256 c41515b79e457d887fda319786ffe95f9d22632cb043489436bb2b32fe83234d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page