Feat: Adding Mem0 Integration (#4339)
* feat(frontend): adding Mem0 Icon * feat(dependencies): adding and setting Mem0 dependency * feat(frontend): adding Mem0 Icon * feat: adding Mem0 components * feat(dependencies): adding and setting Mem0 dependency * Update uv.lock update uv for memo * update and delete mem0 removed update and delete mem0 removed as per suggestion * update requirement --------- Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
This commit is contained in:
parent
76c91de563
commit
5a6c556e36
6 changed files with 1222 additions and 1496 deletions
|
|
@ -115,6 +115,7 @@ dependencies = [
|
|||
"langchain-ollama>=0.2.0",
|
||||
"sqlalchemy[aiosqlite,postgresql_psycopg2binary,postgresql_psycopgbinary]>=2.0.36",
|
||||
"atlassian-python-api>=3.41.16",
|
||||
"mem0ai>=0.1.26",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,144 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
from mem0 import Memory, MemoryClient
|
||||
|
||||
from langflow.base.memory.model import LCChatMemoryComponent
|
||||
from langflow.inputs import (
|
||||
DictInput,
|
||||
HandleInput,
|
||||
MessageTextInput,
|
||||
NestedDictInput,
|
||||
SecretStrInput,
|
||||
)
|
||||
from langflow.io import Output
|
||||
from langflow.schema import Data
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Mem0MemoryComponent(LCChatMemoryComponent):
|
||||
display_name = "Mem0 Chat Memory"
|
||||
description = "Retrieves and stores chat messages using Mem0 memory storage."
|
||||
name = "mem0_chat_memory"
|
||||
icon: str = "Mem0"
|
||||
inputs = [
|
||||
NestedDictInput(
|
||||
name="mem0_config",
|
||||
display_name="Mem0 Configuration",
|
||||
info="""Configuration dictionary for initializing Mem0 memory instance.
|
||||
Example:
|
||||
{
|
||||
"graph_store": {
|
||||
"provider": "neo4j",
|
||||
"config": {
|
||||
"url": "neo4j+s://your-neo4j-url",
|
||||
"username": "neo4j",
|
||||
"password": "your-password"
|
||||
}
|
||||
},
|
||||
"version": "v1.1"
|
||||
}""",
|
||||
input_types=["Data"],
|
||||
),
|
||||
MessageTextInput(
|
||||
name="ingest_message",
|
||||
display_name="Message to Ingest",
|
||||
info="The message content to be ingested into Mem0 memory.",
|
||||
),
|
||||
HandleInput(
|
||||
name="existing_memory",
|
||||
display_name="Existing Memory Instance",
|
||||
input_types=["Memory"],
|
||||
info="Optional existing Mem0 memory instance. If not provided, a new instance will be created.",
|
||||
),
|
||||
MessageTextInput(
|
||||
name="user_id", display_name="User ID", info="Identifier for the user associated with the messages."
|
||||
),
|
||||
MessageTextInput(
|
||||
name="search_query", display_name="Search Query", info="Input text for searching related memories in Mem0."
|
||||
),
|
||||
SecretStrInput(
|
||||
name="mem0_api_key",
|
||||
display_name="Mem0 API Key",
|
||||
info="API key for Mem0 platform. Leave empty to use the local version.",
|
||||
),
|
||||
DictInput(
|
||||
name="metadata",
|
||||
display_name="Metadata",
|
||||
info="Additional metadata to associate with the ingested message.",
|
||||
advanced=True,
|
||||
),
|
||||
SecretStrInput(
|
||||
name="openai_api_key",
|
||||
display_name="OpenAI API Key",
|
||||
required=False,
|
||||
info="API key for OpenAI. Required if using OpenAI Embeddings without a provided configuration.",
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(name="memory", display_name="Mem0 Memory", method="ingest_data"),
|
||||
Output(
|
||||
name="search_results",
|
||||
display_name="Search Results",
|
||||
method="build_search_results",
|
||||
),
|
||||
]
|
||||
|
||||
def build_mem0(self) -> Memory:
|
||||
"""Initializes a Mem0 memory instance based on provided configuration and API keys."""
|
||||
if self.openai_api_key:
|
||||
os.environ["OPENAI_API_KEY"] = self.openai_api_key
|
||||
|
||||
try:
|
||||
if not self.mem0_api_key:
|
||||
return Memory.from_config(config_dict=dict(self.mem0_config)) if self.mem0_config else Memory()
|
||||
if self.mem0_config:
|
||||
return MemoryClient.from_config(api_key=self.mem0_api_key, config_dict=dict(self.mem0_config))
|
||||
return MemoryClient(api_key=self.mem0_api_key)
|
||||
except ImportError as e:
|
||||
msg = "Mem0 is not properly installed. Please install it with 'pip install -U mem0ai'."
|
||||
raise ImportError(msg) from e
|
||||
|
||||
def ingest_data(self) -> Memory:
|
||||
"""Ingests a new message into Mem0 memory and returns the updated memory instance."""
|
||||
mem0_memory = self.existing_memory if self.existing_memory else self.build_mem0()
|
||||
|
||||
if not self.ingest_message or not self.user_id:
|
||||
logger.warning("Missing 'ingest_message' or 'user_id'; cannot ingest data.")
|
||||
return mem0_memory
|
||||
|
||||
metadata = self.metadata if self.metadata else {}
|
||||
|
||||
logger.info("Ingesting message for user_id: %s", self.user_id)
|
||||
|
||||
try:
|
||||
mem0_memory.add(self.ingest_message, user_id=self.user_id, metadata=metadata)
|
||||
except Exception:
|
||||
logger.exception("Failed to add message to Mem0 memory.")
|
||||
raise
|
||||
|
||||
return mem0_memory
|
||||
|
||||
def build_search_results(self) -> Data:
|
||||
"""Searches the Mem0 memory for related messages based on the search query and returns the results."""
|
||||
mem0_memory = self.ingest_data()
|
||||
search_query = self.search_query
|
||||
user_id = self.user_id
|
||||
|
||||
logger.info("Search query: %s", search_query)
|
||||
|
||||
try:
|
||||
if search_query:
|
||||
logger.info("Performing search with query.")
|
||||
related_memories = mem0_memory.search(query=search_query, user_id=user_id)
|
||||
else:
|
||||
logger.info("Retrieving all memories for user_id: %s", user_id)
|
||||
related_memories = mem0_memory.get_all(user_id=user_id)
|
||||
except Exception:
|
||||
logger.exception("Failed to retrieve related memories from Mem0.")
|
||||
raise
|
||||
|
||||
logger.info("Related memories retrieved: %s", related_memories)
|
||||
return related_memories
|
||||
36
src/frontend/src/icons/Mem0/SvgMem.jsx
Normal file
36
src/frontend/src/icons/Mem0/SvgMem.jsx
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
export default function SvgMem0(props) {
|
||||
return (
|
||||
<svg
|
||||
width="126pt"
|
||||
height="127pt"
|
||||
viewBox="0 0 126 127"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<g
|
||||
transform="translate(0.000000,127.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000"
|
||||
stroke="none"
|
||||
>
|
||||
<path d="M648 1248 c-26 -22 -29 -47 -8 -68 25 -25 42 -25 63 -2 22 24 21 45 -1 65 -22 20 -33 21 -54 5z" />
|
||||
<path d="M440 1201 c-16 -4 -32 -21 -44 -45 -19 -38 -19 -39 3 -82 30 -64 27 -79 -23 -113 -66 -46 -75 -93 -27 -142 35 -34 68 -37 105 -8 45 35 50 63 21 120 -30 57 -25 75 29 108 45 28 60 71 42 116 -8 18 -18 35 -22 37 -19 11 -60 15 -84 9z" />
|
||||
<path d="M807 1160 c-15 -12 -29 -36 -33 -55 -10 -57 -48 -74 -106 -50 -9 4 -33 1 -53 -5 -89 -29 -64 -164 30 -164 29 0 43 7 61 28 13 15 24 35 24 44 0 10 7 28 16 41 15 21 21 23 79 16 57 -6 65 -4 91 18 82 71 -24 194 -109 127z" />
|
||||
<path d="M231 1104 c-38 -27 -22 -84 25 -84 29 0 46 23 42 56 -4 34 -37 48 -67 28z" />
|
||||
<path d="M1032 1048 c-28 -28 -7 -78 33 -78 12 0 26 5 33 12 7 7 12 21 12 33 0 12 -5 26 -12 33 -7 7 -21 12 -33 12 -12 0 -26 -5 -33 -12z" />
|
||||
<path d="M841 946 c-55 -31 -65 -93 -22 -137 35 -35 73 -38 116 -9 42 28 59 25 89 -12 50 -64 55 -68 94 -68 78 0 113 93 56 145 -32 30 -55 31 -113 5 -55 -25 -75 -19 -107 31 -13 22 -36 44 -50 49 -32 12 -34 12 -63 -4z" />
|
||||
<path d="M119 921 c-51 -52 -33 -119 39 -141 65 -21 73 -35 66 -106 -6 -58 -5 -64 19 -88 36 -36 80 -35 118 3 32 33 36 58 14 100 -10 21 -26 31 -59 40 -57 14 -68 33 -60 108 6 54 4 60 -21 86 -37 36 -78 36 -116 -2z" />
|
||||
<path d="M592 783 c-36 -7 -89 -65 -101 -109 -17 -64 8 -132 62 -164 43 -26 121 -26 164 0 86 52 88 189 3 251 -26 19 -89 30 -128 22z" />
|
||||
<path d="M26 699 c-20 -30 -6 -63 28 -67 49 -6 74 38 40 72 -22 22 -50 20 -68 -5z" />
|
||||
<path d="M928 704 c-31 -16 -51 -62 -42 -98 7 -29 48 -66 73 -66 9 0 27 -7 39 -16 22 -15 23 -21 17 -78 -6 -53 -4 -64 15 -89 46 -58 150 -21 150 53 0 36 -46 90 -77 90 -10 0 -29 7 -41 16 -20 14 -22 21 -16 82 4 49 2 72 -8 85 -20 26 -79 37 -110 21z" />
|
||||
<path d="M1177 632 c-22 -24 -21 -45 1 -65 25 -23 48 -21 66 5 20 29 20 34 -4 58 -25 25 -42 25 -63 2z" />
|
||||
<path d="M113 550 c-47 -19 -59 -102 -21 -137 36 -32 57 -35 105 -13 60 26 78 25 100 -6 37 -55 62 -74 93 -74 37 0 90 47 90 80 0 35 -27 76 -58 89 -26 11 -36 9 -81 -14 -60 -30 -77 -25 -110 30 -28 48 -70 64 -118 45z" />
|
||||
<path d="M806 454 c-32 -33 -34 -74 -5 -120 26 -43 18 -68 -31 -99 -47 -29 -52 -37 -53 -80 -2 -70 77 -109 138 -69 35 23 41 65 15 117 -28 56 -24 75 25 108 48 33 67 71 53 111 -22 61 -96 78 -142 32z" />
|
||||
<path d="M572 370 c-12 -11 -26 -38 -32 -60 -13 -47 -43 -67 -87 -55 -93 26 -160 -53 -110 -129 39 -59 131 -38 152 36 18 62 30 70 101 63 58 -7 64 -5 88 18 42 42 34 107 -15 132 -39 21 -71 19 -97 -5z" />
|
||||
<path d="M190 297 c-45 -22 -34 -87 14 -87 45 0 62 52 28 83 -15 13 -22 14 -42 4z" />
|
||||
<path d="M987 242 c-32 -35 -15 -82 28 -82 44 0 61 52 27 83 -24 22 -35 21 -55 -1z" />
|
||||
<path d="M566 94 c-33 -32 -13 -74 36 -74 38 0 55 33 33 66 -18 28 -46 31 -69 8z" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
8
src/frontend/src/icons/Mem0/index.tsx
Normal file
8
src/frontend/src/icons/Mem0/index.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import SvgMem from "./SvgMem";
|
||||
|
||||
export const Mem0 = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <SvgMem className="icon" ref={ref} {...props} />;
|
||||
},
|
||||
);
|
||||
|
|
@ -238,6 +238,7 @@ import { IFixIcon } from "../icons/IFixIt";
|
|||
import { LMStudioIcon } from "../icons/LMStudio";
|
||||
import { LangChainIcon } from "../icons/LangChain";
|
||||
import { MaritalkIcon } from "../icons/Maritalk";
|
||||
import { Mem0 } from "../icons/Mem0";
|
||||
import { MetaIcon } from "../icons/Meta";
|
||||
import { MidjourneyIcon } from "../icons/Midjorney";
|
||||
import { MongoDBIcon } from "../icons/MongoDB";
|
||||
|
|
@ -826,4 +827,5 @@ export const nodeIconsLucide: iconsType = {
|
|||
CircleCheckBig,
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
Mem0,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue