Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dfa9b4412 | ||
|
|
5509066925 | ||
|
|
3712522b14 | ||
|
|
93f34e4116 | ||
|
|
39e5cbfacc | ||
|
|
d30c78c5eb | ||
|
|
039756abbe | ||
|
|
cb38c2dae7 | ||
|
|
4dc9f6fad6 | ||
|
|
1b1f02eb57 | ||
|
|
1db1105cad | ||
|
|
91a28c7f04 | ||
|
|
a78e1894b1 | ||
|
|
83338295d8 | ||
|
|
aff70807c6 | ||
|
|
648c86b53d | ||
|
|
de0b2de9c2 | ||
|
|
e3f460fba4 | ||
|
|
fe7b336922 | ||
|
|
1033ab227c | ||
|
|
5ed15c3bcd | ||
|
|
c1f5a655ba |
@@ -13,7 +13,7 @@ install:
|
||||
install_all:
|
||||
poetry install
|
||||
poetry run pip install groq together boto3 litellm ollama chromadb weaviate weaviate-client sentence_transformers vertexai \
|
||||
google-generativeai elasticsearch opensearch-py vecs pinecone pinecone-text faiss-cpu
|
||||
google-generativeai elasticsearch opensearch-py vecs pinecone pinecone-text faiss-cpu langchain-community
|
||||
|
||||
# Format code with ruff
|
||||
format:
|
||||
|
||||
@@ -6,6 +6,40 @@ mode: "wide"
|
||||
<Tabs>
|
||||
<Tab title="Python">
|
||||
|
||||
<Update label="2025-04-07" description="v0.1.84">
|
||||
|
||||
**New Features:**
|
||||
- **Langchain Embedder:** Added Langchain embedder integration
|
||||
|
||||
**Improvements:**
|
||||
- **Langchain LLM:** Updated Langchain LLM integration to directly pass the Langchain object LLM
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-07" description="v0.1.83">
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Langchain LLM:** Fixed issues with Langchain LLM integration
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-07" description="v0.1.82">
|
||||
|
||||
**New Features:**
|
||||
- **LLM Integrations:** Added support for Langchain LLMs, Google as new LLM and embedder
|
||||
- **Development:** Added development docker compose
|
||||
|
||||
**Improvements:**
|
||||
- **Output Format:** Set output_format='v1.1' and updated documentation
|
||||
|
||||
**Documentation:**
|
||||
- **Integrations:** Added LMStudio and Together.ai documentation
|
||||
- **API Reference:** Updated output_format documentation
|
||||
- **Integrations:** Added PipeCat integration documentation
|
||||
- **Integrations:** Added Flowise integration documentation for Mem0 memory setup
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Tests:** Fixed failing unit tests
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-02" description="v0.1.79">
|
||||
|
||||
**New Features:**
|
||||
@@ -56,12 +90,39 @@ mode: "wide"
|
||||
|
||||
<Tab title="TypeScript">
|
||||
|
||||
<Update label="2025-04-01" description="v2.1.14">
|
||||
**New Features:**
|
||||
- **Mastra Example:** Added Mastra example
|
||||
- **Integrations:** Added Flowise integration documentation for Mem0 memory setup
|
||||
|
||||
**Improvements:**
|
||||
- **Demo:** Updated Demo Mem0AI
|
||||
- **Client:** Enhanced Ping method in Mem0 Client
|
||||
- **AI SDK:** Updated AI SDK implementation
|
||||
</Update>
|
||||
|
||||
<Update label="2025-03-29" description="v2.1.13">
|
||||
**Improvements:**
|
||||
- **Introuced `ping` method to check if API key is valid and populate org/project id**
|
||||
</Update>
|
||||
|
||||
<Update label="2025-03-29" description="AI SDK v1.0.0">
|
||||
**New Features:**
|
||||
- **Vercel AI SDK Update:** Support threshold and rerank
|
||||
|
||||
**Improvements:**
|
||||
- **Made add calls async to avoid blocking**
|
||||
- **Bump `mem0ai` to use `2.1.12`**
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-03-26" description="v2.1.12">
|
||||
**New Features:**
|
||||
- **Vercel AI SDK Update:** Support for tools call
|
||||
- **Mem0 OSS:** Support infer param
|
||||
|
||||
**Improvements:**
|
||||
- **Updated Supabase TS Docs**
|
||||
- **Made package size smaller**
|
||||
|
||||
</Update>
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
---
|
||||
title: LangChain
|
||||
---
|
||||
|
||||
Mem0 supports LangChain as a provider to access a wide range of embedding models. LangChain is a framework for developing applications powered by language models, making it easy to integrate various embedding providers through a consistent interface.
|
||||
|
||||
For a complete list of available embedding models supported by LangChain, refer to the [LangChain Text Embedding documentation](https://python.langchain.com/docs/integrations/text_embedding/).
|
||||
|
||||
## Usage
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
from langchain_openai import OpenAIEmbeddings
|
||||
|
||||
# Set necessary environment variables for your chosen LangChain provider
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key"
|
||||
|
||||
# Initialize a LangChain embeddings model directly
|
||||
openai_embeddings = OpenAIEmbeddings(
|
||||
model="text-embedding-3-small",
|
||||
dimensions=1536
|
||||
)
|
||||
|
||||
# Pass the initialized model to the config
|
||||
config = {
|
||||
"embedder": {
|
||||
"provider": "langchain",
|
||||
"config": {
|
||||
"model": openai_embeddings
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
||||
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
|
||||
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
||||
]
|
||||
m.add(messages, user_id="alice", metadata={"category": "movies"})
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Supported LangChain Embedding Providers
|
||||
|
||||
LangChain supports a wide range of embedding providers, including:
|
||||
|
||||
- OpenAI (`OpenAIEmbeddings`)
|
||||
- Cohere (`CohereEmbeddings`)
|
||||
- Google (`VertexAIEmbeddings`)
|
||||
- Hugging Face (`HuggingFaceEmbeddings`)
|
||||
- Sentence Transformers (`HuggingFaceEmbeddings`)
|
||||
- Azure OpenAI (`AzureOpenAIEmbeddings`)
|
||||
- Ollama (`OllamaEmbeddings`)
|
||||
- Together (`TogetherEmbeddings`)
|
||||
- And many more
|
||||
|
||||
You can use any of these model instances directly in your configuration. For a complete and up-to-date list of available embedding providers, refer to the [LangChain Text Embedding documentation](https://python.langchain.com/docs/integrations/text_embedding/).
|
||||
|
||||
## Provider-Specific Configuration
|
||||
|
||||
When using LangChain as an embedder provider, you'll need to:
|
||||
|
||||
1. Set the appropriate environment variables for your chosen embedding provider
|
||||
2. Import and initialize the specific model class you want to use
|
||||
3. Pass the initialized model instance to the config
|
||||
|
||||
### Examples with Different Providers
|
||||
|
||||
#### HuggingFace Embeddings
|
||||
|
||||
```python
|
||||
from langchain_huggingface import HuggingFaceEmbeddings
|
||||
|
||||
# Initialize a HuggingFace embeddings model
|
||||
hf_embeddings = HuggingFaceEmbeddings(
|
||||
model_name="BAAI/bge-small-en-v1.5",
|
||||
encode_kwargs={"normalize_embeddings": True}
|
||||
)
|
||||
|
||||
config = {
|
||||
"embedder": {
|
||||
"provider": "langchain",
|
||||
"config": {
|
||||
"model": hf_embeddings
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Ollama Embeddings
|
||||
|
||||
```python
|
||||
from langchain_ollama import OllamaEmbeddings
|
||||
|
||||
# Initialize an Ollama embeddings model
|
||||
ollama_embeddings = OllamaEmbeddings(
|
||||
model="nomic-embed-text"
|
||||
)
|
||||
|
||||
config = {
|
||||
"embedder": {
|
||||
"provider": "langchain",
|
||||
"config": {
|
||||
"model": ollama_embeddings
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
Make sure to install the necessary LangChain packages and any provider-specific dependencies.
|
||||
</Note>
|
||||
|
||||
## Config
|
||||
|
||||
All available parameters for the `langchain` embedder config are present in [Master List of All Params in Config](../config).
|
||||
@@ -23,6 +23,7 @@ See the list of supported embedders below.
|
||||
<Card title="Vertex AI" href="/components/embedders/models/vertexai"></Card>
|
||||
<Card title="Together" href="/components/embedders/models/together"></Card>
|
||||
<Card title="LM Studio" href="/components/embedders/models/lmstudio"></Card>
|
||||
<Card title="Langchain" href="/components/embedders/models/langchain"></Card>
|
||||
</CardGroup>
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
title: LangChain
|
||||
---
|
||||
|
||||
Mem0 supports LangChain as a provider to access a wide range of LLM models. LangChain is a framework for developing applications powered by language models, making it easy to integrate various LLM providers through a consistent interface.
|
||||
|
||||
For a complete list of available chat models supported by LangChain, refer to the [LangChain Chat Models documentation](https://python.langchain.com/docs/integrations/chat).
|
||||
|
||||
## Usage
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
from langchain_openai import ChatOpenAI
|
||||
|
||||
# Set necessary environment variables for your chosen LangChain provider
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key"
|
||||
|
||||
# Initialize a LangChain model directly
|
||||
openai_model = ChatOpenAI(
|
||||
model="gpt-4o",
|
||||
temperature=0.2,
|
||||
max_tokens=2000
|
||||
)
|
||||
|
||||
# Pass the initialized model to the config
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "langchain",
|
||||
"config": {
|
||||
"model": openai_model
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
||||
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
|
||||
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
||||
]
|
||||
m.add(messages, user_id="alice", metadata={"category": "movies"})
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Supported LangChain Providers
|
||||
|
||||
LangChain supports a wide range of LLM providers, including:
|
||||
|
||||
- OpenAI (`ChatOpenAI`)
|
||||
- Anthropic (`ChatAnthropic`)
|
||||
- Google (`ChatGoogleGenerativeAI`, `ChatGooglePalm`)
|
||||
- Mistral (`ChatMistralAI`)
|
||||
- Ollama (`ChatOllama`)
|
||||
- Azure OpenAI (`AzureChatOpenAI`)
|
||||
- HuggingFace (`HuggingFaceChatEndpoint`)
|
||||
- And many more
|
||||
|
||||
You can use any of these model instances directly in your configuration. For a complete and up-to-date list of available providers, refer to the [LangChain Chat Models documentation](https://python.langchain.com/docs/integrations/chat).
|
||||
|
||||
## Provider-Specific Configuration
|
||||
|
||||
When using LangChain as a provider, you'll need to:
|
||||
|
||||
1. Set the appropriate environment variables for your chosen LLM provider
|
||||
2. Import and initialize the specific model class you want to use
|
||||
3. Pass the initialized model instance to the config
|
||||
|
||||
<Note>
|
||||
Make sure to install the necessary LangChain packages and any provider-specific dependencies.
|
||||
</Note>
|
||||
|
||||
## Config
|
||||
|
||||
All available parameters for the `langchain` config are present in [Master List of All Params in Config](../config).
|
||||
@@ -33,6 +33,7 @@ To view all supported llms, visit the [Supported LLMs](./models).
|
||||
<Card title="DeepSeek" href="/components/llms/models/deepseek" />
|
||||
<Card title="xAI" href="/components/llms/models/xAI" />
|
||||
<Card title="LM Studio" href="/components/llms/models/lmstudio" />
|
||||
<Card title="Langchain" href="/components/llms/models/langchain" />
|
||||
</CardGroup>
|
||||
|
||||
## Structured vs Unstructured Outputs
|
||||
|
||||
+4
@@ -1,3 +1,7 @@
|
||||
---
|
||||
title: Azure AI Search
|
||||
---
|
||||
|
||||
[Azure AI Search](https://learn.microsoft.com/azure/search/search-what-is-azure-search/) (formerly known as "Azure Cognitive Search") provides secure information retrieval at scale over user-owned content in traditional and generative AI search applications.
|
||||
|
||||
## Usage
|
||||
+3
-1
@@ -1,4 +1,6 @@
|
||||
## Google Cloud Vertex AI Vector Search
|
||||
---
|
||||
title: Vertex AI Vector Search
|
||||
---
|
||||
|
||||
|
||||
### Usage
|
||||
@@ -20,12 +20,12 @@ See the list of supported vector databases below.
|
||||
<Card title="Pgvector" href="/components/vectordbs/dbs/pgvector"></Card>
|
||||
<Card title="Milvus" href="/components/vectordbs/dbs/milvus"></Card>
|
||||
<Card title="Pinecone" href="/components/vectordbs/dbs/pinecone"></Card>
|
||||
<Card title="Azure AI Search" href="/components/vectordbs/dbs/azure_ai_search"></Card>
|
||||
<Card title="Azure" href="/components/vectordbs/dbs/azure"></Card>
|
||||
<Card title="Redis" href="/components/vectordbs/dbs/redis"></Card>
|
||||
<Card title="Elasticsearch" href="/components/vectordbs/dbs/elasticsearch"></Card>
|
||||
<Card title="OpenSearch" href="/components/vectordbs/dbs/opensearch"></Card>
|
||||
<Card title="Supabase" href="/components/vectordbs/dbs/supabase"></Card>
|
||||
<Card title="Vertex AI Vector Search" href="/components/vectordbs/dbs/vertex_ai_vector_search"></Card>
|
||||
<Card title="Vertex AI" href="/components/vectordbs/dbs/vertex_ai"></Card>
|
||||
<Card title="Weaviate" href="/components/vectordbs/dbs/weaviate"></Card>
|
||||
<Card title="FAISS" href="/components/vectordbs/dbs/faiss"></Card>
|
||||
</CardGroup>
|
||||
|
||||
+13
-5
@@ -110,7 +110,9 @@
|
||||
"components/llms/models/aws_bedrock",
|
||||
"components/llms/models/gemini",
|
||||
"components/llms/models/deepseek",
|
||||
"components/llms/models/xAI"
|
||||
"components/llms/models/xAI",
|
||||
"components/llms/models/lmstudio",
|
||||
"components/llms/models/langchain"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -130,12 +132,12 @@
|
||||
"components/vectordbs/dbs/pgvector",
|
||||
"components/vectordbs/dbs/milvus",
|
||||
"components/vectordbs/dbs/pinecone",
|
||||
"components/vectordbs/dbs/azure_ai_search",
|
||||
"components/vectordbs/dbs/azure",
|
||||
"components/vectordbs/dbs/redis",
|
||||
"components/vectordbs/dbs/elasticsearch",
|
||||
"components/vectordbs/dbs/opensearch",
|
||||
"components/vectordbs/dbs/supabase",
|
||||
"components/vectordbs/dbs/vertex_ai_vector_search",
|
||||
"components/vectordbs/dbs/vertex_ai",
|
||||
"components/vectordbs/dbs/weaviate",
|
||||
"components/vectordbs/dbs/faiss"
|
||||
]
|
||||
@@ -157,7 +159,10 @@
|
||||
"components/embedders/models/ollama",
|
||||
"components/embedders/models/huggingface",
|
||||
"components/embedders/models/vertexai",
|
||||
"components/embedders/models/gemini"
|
||||
"components/embedders/models/gemini",
|
||||
"components/embedders/models/lmstudio",
|
||||
"components/embedders/models/together",
|
||||
"components/embedders/models/langchain"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -184,6 +189,7 @@
|
||||
"examples/overview",
|
||||
"examples/mem0-demo",
|
||||
"examples/ai_companion_js",
|
||||
"examples/mem0-mastra",
|
||||
"examples/mem0-with-ollama",
|
||||
"examples/personal-ai-tutor",
|
||||
"examples/customer-support-agent",
|
||||
@@ -211,6 +217,7 @@
|
||||
"pages": [
|
||||
"integrations/overview",
|
||||
"integrations/vercel-ai-sdk",
|
||||
"integrations/flowise",
|
||||
"integrations/crewai",
|
||||
"integrations/autogen",
|
||||
"integrations/langchain",
|
||||
@@ -220,7 +227,8 @@
|
||||
"integrations/dify",
|
||||
"integrations/mcp-server",
|
||||
"integrations/livekit",
|
||||
"integrations/elevenlabs"
|
||||
"integrations/elevenlabs",
|
||||
"integrations/pipecat"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
title: Mem0 with Mastra
|
||||
---
|
||||
|
||||
In this example you'll learn how to use the Mem0 to add long-term memory capabilities to [Mastra's agent](https://mastra.ai/) via tool-use.
|
||||
This memory integration can work alongside Mastra's [agent memory features](https://mastra.ai/docs/agents/01-agent-memory).
|
||||
|
||||
You can find the complete example code in the [Mastra repository](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-mem0).
|
||||
|
||||
## Overview
|
||||
|
||||
This guide will show you how to integrate Mem0 with Mastra to add long-term memory capabilities to your agents. We'll create tools that allow agents to save and retrieve memories using Mem0's API.
|
||||
|
||||
### Installation
|
||||
|
||||
1. **Install the Integration Package**
|
||||
|
||||
To install the Mem0 integration, run:
|
||||
|
||||
```bash
|
||||
npm install @mastra/mem0
|
||||
```
|
||||
|
||||
2. **Add the Integration to Your Project**
|
||||
|
||||
Create a new file for your integrations and import the integration:
|
||||
|
||||
```typescript integrations/index.ts
|
||||
import { Mem0Integration } from "@mastra/mem0";
|
||||
|
||||
export const mem0 = new Mem0Integration({
|
||||
config: {
|
||||
apiKey: process.env.MEM0_API_KEY!,
|
||||
userId: "alice",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
3. **Use the Integration in Tools or Workflows**
|
||||
|
||||
You can now use the integration when defining tools for your agents or in workflows.
|
||||
|
||||
```typescript tools/index.ts
|
||||
import { createTool } from "@mastra/core";
|
||||
import { z } from "zod";
|
||||
import { mem0 } from "../integrations";
|
||||
|
||||
export const mem0RememberTool = createTool({
|
||||
id: "Mem0-remember",
|
||||
description:
|
||||
"Remember your agent memories that you've previously saved using the Mem0-memorize tool.",
|
||||
inputSchema: z.object({
|
||||
question: z
|
||||
.string()
|
||||
.describe("Question used to look up the answer in saved memories."),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
answer: z.string().describe("Remembered answer"),
|
||||
}),
|
||||
execute: async ({ context }) => {
|
||||
console.log(`Searching memory "${context.question}"`);
|
||||
const memory = await mem0.searchMemory(context.question);
|
||||
console.log(`\nFound memory "${memory}"\n`);
|
||||
|
||||
return {
|
||||
answer: memory,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const mem0MemorizeTool = createTool({
|
||||
id: "Mem0-memorize",
|
||||
description:
|
||||
"Save information to mem0 so you can remember it later using the Mem0-remember tool.",
|
||||
inputSchema: z.object({
|
||||
statement: z.string().describe("A statement to save into memory"),
|
||||
}),
|
||||
execute: async ({ context }) => {
|
||||
console.log(`\nCreating memory "${context.statement}"\n`);
|
||||
// to reduce latency memories can be saved async without blocking tool execution
|
||||
void mem0.createMemory(context.statement).then(() => {
|
||||
console.log(`\nMemory "${context.statement}" saved.\n`);
|
||||
});
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
4. **Create a new agent**
|
||||
|
||||
```typescript agents/index.ts
|
||||
import { openai } from '@ai-sdk/openai';
|
||||
import { Agent } from '@mastra/core/agent';
|
||||
import { mem0MemorizeTool, mem0RememberTool } from '../tools';
|
||||
|
||||
export const mem0Agent = new Agent({
|
||||
name: 'Mem0 Agent',
|
||||
instructions: `
|
||||
You are a helpful assistant that has the ability to memorize and remember facts using Mem0.
|
||||
`,
|
||||
model: openai('gpt-4o'),
|
||||
tools: { mem0RememberTool, mem0MemorizeTool },
|
||||
});
|
||||
```
|
||||
|
||||
5. **Run the agent**
|
||||
|
||||
```typescript index.ts
|
||||
import { Mastra } from '@mastra/core/mastra';
|
||||
import { createLogger } from '@mastra/core/logger';
|
||||
|
||||
import { mem0Agent } from './agents';
|
||||
|
||||
export const mastra = new Mastra({
|
||||
agents: { mem0Agent },
|
||||
logger: createLogger({
|
||||
name: 'Mastra',
|
||||
level: 'error',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
In the example above:
|
||||
- We import the `@mastra/mem0` integration.
|
||||
- We define two tools that uses the Mem0 API client to create new memories and recall previously saved memories.
|
||||
- The tool accepts `question` as an input and returns the memory as a string.
|
||||
@@ -125,6 +125,23 @@ iconType: "solid"
|
||||
This flexibility allows you to create highly contextually aware AI applications that can adapt to specific user needs and situations. Metadata provides an additional dimension for memory retrieval, enabling more precise and relevant responses.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do I disable telemetry in Mem0?">
|
||||
To disable telemetry in Mem0, you can set the `MEM0_TELEMETRY` environment variable to `False`:
|
||||
|
||||
```bash
|
||||
MEM0_TELEMETRY=False
|
||||
```
|
||||
|
||||
You can also disable telemetry programmatically in your code:
|
||||
|
||||
```python
|
||||
import os
|
||||
os.environ["MEM0_TELEMETRY"] = "False"
|
||||
```
|
||||
|
||||
Setting this environment variable will prevent Mem0 from collecting and sending any usage data, ensuring complete privacy for your application.
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
title: Flowise
|
||||
---
|
||||
|
||||
The [**Mem0 Memory**](https://github.com/mem0ai/mem0) integration with [Flowise](https://github.com/FlowiseAI/Flowise) enables persistent memory capabilities for your AI chatflows. [Flowise](https://flowiseai.com/) is an open-source low-code tool for developers to build customized LLM orchestration flows & AI agents using a drag & drop interface.
|
||||
|
||||
## Overview
|
||||
|
||||
1. 🧠 Provides persistent memory storage for Flowise chatflows
|
||||
2. 🔄 Seamless integration with existing Flowise templates
|
||||
3. 🚀 Compatible with various LLM nodes in Flowise
|
||||
4. 📝 Supports custom memory configurations
|
||||
5. ⚡ Easy to set up and manage
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before setting up Mem0 with Flowise, ensure you have:
|
||||
|
||||
1. [Flowise installed](https://github.com/FlowiseAI/Flowise#⚡quick-start) (NodeJS >= 18.15.0 required):
|
||||
```bash
|
||||
npm install -g flowise
|
||||
npx flowise start
|
||||
```
|
||||
|
||||
2. Access to the Flowise UI at http://localhost:3000
|
||||
3. Basic familiarity with [Flowise's LLM orchestration](https://flowiseai.com/#features) concepts
|
||||
|
||||
## Setup and Configuration
|
||||
|
||||
### 1. Set Up Flowise
|
||||
|
||||
1. Open the Flowise application and create a new canvas, or select a template from the Flowise marketplace.
|
||||
2. In this example, we use the **Conversation Chain** template.
|
||||
3. Replace the default **Buffer Memory** with **Mem0 Memory**.
|
||||
|
||||

|
||||
|
||||
### 2. Obtain Your Mem0 API Key
|
||||
|
||||
1. Navigate to the [Mem0 API Key dashboard](https://app.mem0.ai/dashboard/api-keys).
|
||||
2. Generate or copy your existing Mem0 API Key.
|
||||
|
||||

|
||||
|
||||
### 3. Configure Mem0 Credentials
|
||||
|
||||
1. Enter the **Mem0 API Key** in the Mem0 Credentials section.
|
||||
2. Configure additional settings as needed:
|
||||
|
||||
```typescript
|
||||
{
|
||||
"apiKey": "m0-xxx",
|
||||
"userId": "user-123", // Optional: Specify user ID
|
||||
"projectId": "proj-xxx", // Optional: Specify project ID
|
||||
"orgId": "org-xxx" // Optional: Specify organization ID
|
||||
}
|
||||
```
|
||||
|
||||
<figure>
|
||||
<img src="https://raw.githubusercontent.com/FlowiseAI/FlowiseDocs/main/en/.gitbook/assets/mem0/creds.png" alt="Mem0 Credentials" />
|
||||
<figcaption>Configure API Credentials</figcaption>
|
||||
</figure>
|
||||
|
||||
## Memory Features
|
||||
|
||||
### 1. Basic Memory Storage
|
||||
|
||||
Test your memory configuration:
|
||||
|
||||
1. Save your Flowise configuration
|
||||
2. Run a test chat and store some information
|
||||
3. Verify the stored memories in the [Mem0 Dashboard](https://app.mem0.ai/dashboard/requests)
|
||||
|
||||

|
||||
|
||||
### 2. Memory Retention
|
||||
|
||||
Validate memory persistence:
|
||||
|
||||
1. Clear the chat history in Flowise
|
||||
2. Ask a question about previously stored information
|
||||
3. Confirm that the AI remembers the context
|
||||
|
||||

|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Memory Settings
|
||||
|
||||

|
||||
|
||||
Available settings include:
|
||||
|
||||
1. **Search Only Mode**: Enable memory retrieval without creating new memories
|
||||
2. **Mem0 Entities**: Configure identifiers:
|
||||
- `user_id`: Unique identifier for each user
|
||||
- `run_id`: Specific conversation session ID
|
||||
- `app_id`: Application identifier
|
||||
- `agent_id`: AI agent identifier
|
||||
3. **Project ID**: Assign memories to specific projects
|
||||
4. **Organization ID**: Organize memories by organization
|
||||
|
||||
### Platform Configuration
|
||||
|
||||
Additional settings available in [Mem0 Project Settings](https://app.mem0.ai/dashboard/project-settings):
|
||||
|
||||
1. **Custom Instructions**: Define memory extraction rules
|
||||
2. **Expiration Date**: Set automatic memory cleanup periods
|
||||
|
||||

|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **User Identification**: Use consistent `user_id` values for reliable memory retrieval
|
||||
2. **Memory Organization**: Utilize projects and organizations for better memory management
|
||||
3. **Regular Maintenance**: Monitor and clean up unused memories periodically
|
||||
|
||||
## Help & Resources
|
||||
|
||||
- [Flowise Documentation](https://flowiseai.com/docs)
|
||||
- [Flowise GitHub Repository](https://github.com/FlowiseAI/Flowise)
|
||||
- [Flowise Website](https://flowiseai.com/)
|
||||
- [Mem0 Platform](https://app.mem0.ai/)
|
||||
- Need assistance? Reach out through:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -265,4 +265,25 @@ Here are the available integrations for Mem0:
|
||||
>
|
||||
Build voice agents with memory using ElevenLabs Conversational AI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Pipecat"
|
||||
icon={
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" fill="currentColor"/>
|
||||
<circle cx="8.5" cy="9" r="1.5" fill="currentColor"/>
|
||||
<circle cx="15.5" cy="9" r="1.5" fill="currentColor"/>
|
||||
<path d="M12 16c1.66 0 3-1.34 3-3H9c0 1.66 1.34 3 3 3z" fill="currentColor"/>
|
||||
<path d="M17.5 12c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" fill="currentColor"/>
|
||||
<path d="M6.5 12c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9s1.5.67 1.5 1.5S7.33 12 6.5 12z" fill="currentColor"/>
|
||||
</svg>
|
||||
}
|
||||
href="/integrations/pipecat"
|
||||
>
|
||||
Build conversational AI agents with memory using Pipecat.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
---
|
||||
title: 'Pipecat'
|
||||
description: 'Integrate Mem0 with Pipecat for conversational memory in AI agents'
|
||||
---
|
||||
|
||||
# Pipecat Integration
|
||||
|
||||
Mem0 seamlessly integrates with [Pipecat](https://pipecat.ai), providing long-term memory capabilities for conversational AI agents. This integration allows your Pipecat-powered applications to remember past conversations and provide personalized responses based on user history.
|
||||
|
||||
## Installation
|
||||
|
||||
To use Mem0 with Pipecat, install the required dependencies:
|
||||
|
||||
```bash
|
||||
pip install "pipecat-ai[mem0]"
|
||||
```
|
||||
|
||||
You'll also need to set up your Mem0 API key as an environment variable:
|
||||
|
||||
```bash
|
||||
export MEM0_API_KEY=your_mem0_api_key
|
||||
```
|
||||
|
||||
You can obtain a Mem0 API key by signing up at [mem0.ai](https://mem0.ai).
|
||||
|
||||
## Configuration
|
||||
|
||||
Mem0 integration is provided through the `Mem0MemoryService` class in Pipecat. Here's how to configure it:
|
||||
|
||||
```python
|
||||
from pipecat.services.mem0 import Mem0MemoryService
|
||||
|
||||
memory = Mem0MemoryService(
|
||||
api_key=os.getenv("MEM0_API_KEY"), # Your Mem0 API key
|
||||
user_id="unique_user_id", # Unique identifier for the end user
|
||||
agent_id="my_agent", # Identifier for the agent using the memory
|
||||
run_id="session_123", # Optional: specific conversation session ID
|
||||
params={ # Optional: configuration parameters
|
||||
"search_limit": 10, # Maximum memories to retrieve per query
|
||||
"search_threshold": 0.1, # Relevance threshold (0.0 to 1.0)
|
||||
"system_prompt": "Here are your past memories:", # Custom prefix for memories
|
||||
"add_as_system_message": True, # Add memories as system (True) or user (False) message
|
||||
"position": 1, # Position in context to insert memories
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Pipeline Integration
|
||||
|
||||
The `Mem0MemoryService` should be positioned between your context aggregator and LLM service in the Pipecat pipeline:
|
||||
|
||||
```python
|
||||
pipeline = Pipeline([
|
||||
transport.input(),
|
||||
stt, # Speech-to-text for audio input
|
||||
user_context, # User context aggregator
|
||||
memory, # Mem0 Memory service enhances context here
|
||||
llm, # LLM for response generation
|
||||
tts, # Optional: Text-to-speech
|
||||
transport.output(),
|
||||
assistant_context # Assistant context aggregator
|
||||
])
|
||||
```
|
||||
|
||||
## Example: Voice Agent with Memory
|
||||
|
||||
Here's a complete example of a Pipecat voice agent with Mem0 memory integration:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import os
|
||||
from fastapi import FastAPI, WebSocket
|
||||
|
||||
from pipecat.frames.frames import TextFrame
|
||||
from pipecat.pipeline.pipeline import Pipeline
|
||||
from pipecat.pipeline.task import PipelineTask
|
||||
from pipecat.pipeline.runner import PipelineRunner
|
||||
from pipecat.services.mem0 import Mem0MemoryService
|
||||
from pipecat.services.openai import OpenAILLMService, OpenAIUserContextAggregator, OpenAIAssistantContextAggregator
|
||||
from pipecat.transports.network.fastapi_websocket import (
|
||||
FastAPIWebsocketTransport,
|
||||
FastAPIWebsocketParams
|
||||
)
|
||||
from pipecat.serializers.protobuf import ProtobufFrameSerializer
|
||||
from pipecat.audio.vad.silero import SileroVADAnalyzer
|
||||
from pipecat.services.whisper import WhisperSTTService
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.websocket("/chat")
|
||||
async def websocket_endpoint(websocket: WebSocket):
|
||||
await websocket.accept()
|
||||
|
||||
# Basic setup with minimal configuration
|
||||
user_id = "user123"
|
||||
|
||||
# WebSocket transport
|
||||
transport = FastAPIWebsocketTransport(
|
||||
websocket=websocket,
|
||||
params=FastAPIWebsocketParams(
|
||||
audio_out_enabled=True,
|
||||
vad_enabled=True,
|
||||
vad_analyzer=SileroVADAnalyzer(),
|
||||
vad_audio_passthrough=True,
|
||||
serializer=ProtobufFrameSerializer(),
|
||||
)
|
||||
)
|
||||
|
||||
# Core services
|
||||
user_context = OpenAIUserContextAggregator()
|
||||
assistant_context = OpenAIAssistantContextAggregator()
|
||||
stt = WhisperSTTService(api_key=os.getenv("OPENAI_API_KEY"))
|
||||
|
||||
# Memory service - the key component
|
||||
memory = Mem0MemoryService(
|
||||
api_key=os.getenv("MEM0_API_KEY"),
|
||||
user_id=user_id,
|
||||
agent_id="fastapi_memory_bot"
|
||||
)
|
||||
|
||||
# LLM for response generation
|
||||
llm = OpenAILLMService(
|
||||
api_key=os.getenv("OPENAI_API_KEY"),
|
||||
model="gpt-3.5-turbo",
|
||||
system_prompt="You are a helpful assistant that remembers past conversations."
|
||||
)
|
||||
|
||||
# Simple pipeline
|
||||
pipeline = Pipeline([
|
||||
transport.input(),
|
||||
stt, # Speech-to-text for audio input
|
||||
user_context,
|
||||
memory, # Memory service enhances context here
|
||||
llm,
|
||||
transport.output(),
|
||||
assistant_context
|
||||
])
|
||||
|
||||
# Run the pipeline
|
||||
runner = PipelineRunner()
|
||||
task = PipelineTask(pipeline)
|
||||
|
||||
# Event handlers for WebSocket connections
|
||||
@transport.event_handler("on_client_connected")
|
||||
async def on_client_connected(transport, client):
|
||||
# Send welcome message when client connects
|
||||
await task.queue_frame(TextFrame("Hello! I'm a memory bot. I'll remember our conversation."))
|
||||
|
||||
@transport.event_handler("on_client_disconnected")
|
||||
async def on_client_disconnected(transport, client):
|
||||
# Clean up when client disconnects
|
||||
await task.cancel()
|
||||
|
||||
await runner.run(task)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
When integrated with Pipecat, Mem0 provides two key functionalities:
|
||||
|
||||
### 1. Message Storage
|
||||
|
||||
All conversation messages are automatically stored in Mem0 for future reference:
|
||||
- Captures the full message history from context frames
|
||||
- Associates messages with the specified user, agent, and run IDs
|
||||
- Stores metadata to enable efficient retrieval
|
||||
|
||||
### 2. Memory Retrieval
|
||||
|
||||
When a new user message is detected:
|
||||
1. The message is used as a search query to find relevant past memories
|
||||
2. Relevant memories are retrieved from Mem0's database
|
||||
3. Memories are formatted and added to the conversation context
|
||||
4. The enhanced context is passed to the LLM for response generation
|
||||
|
||||
## Additional Configuration Options
|
||||
|
||||
### Memory Search Parameters
|
||||
|
||||
You can customize how memories are retrieved and used:
|
||||
|
||||
```python
|
||||
memory = Mem0MemoryService(
|
||||
api_key=os.getenv("MEM0_API_KEY"),
|
||||
user_id="user123",
|
||||
params={
|
||||
"search_limit": 5, # Retrieve up to 5 memories
|
||||
"search_threshold": 0.2, # Higher threshold for more relevant matches
|
||||
"api_version": "v2", # Mem0 API version
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Memory Presentation Options
|
||||
|
||||
Control how memories are presented to the LLM:
|
||||
|
||||
```python
|
||||
memory = Mem0MemoryService(
|
||||
api_key=os.getenv("MEM0_API_KEY"),
|
||||
user_id="user123",
|
||||
params={
|
||||
"system_prompt": "Previous conversations with this user:",
|
||||
"add_as_system_message": True, # Add as system message instead of user message
|
||||
"position": 0, # Insert at the beginning of the context
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [Mem0 Pipecat Integration](https://docs.pipecat.ai/server/services/memory/mem0)
|
||||
- [Pipecat Documentation](https://docs.pipecat.ai)
|
||||
|
||||
@@ -10,7 +10,6 @@ The [**Mem0 AI SDK Provider**](https://www.npmjs.com/package/@mem0/vercel-ai-pro
|
||||
|
||||
## Overview
|
||||
|
||||
In this guide, we'll create a Travel Agent AI that:
|
||||
1. 🧠 Offers persistent memory storage for conversational AI
|
||||
2. 🔄 Enables smooth integration with the Vercel AI SDK
|
||||
3. 🚀 Ensures compatibility with multiple LLM providers
|
||||
@@ -191,6 +190,20 @@ npm install @mem0/vercel-ai-provider
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
### 5. Get sources from memory
|
||||
|
||||
```typescript
|
||||
const { text, sources } = await generateText({
|
||||
model: mem0("gpt-4-turbo"),
|
||||
prompt: "Suggest me a good car to buy!",
|
||||
});
|
||||
|
||||
console.log(sources);
|
||||
```
|
||||
|
||||
The same can be done for `streamText` as well.
|
||||
|
||||
|
||||
## Key Features
|
||||
|
||||
- `createMem0()`: Initializes a new Mem0 provider instance.
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
# Mem0
|
||||
|
||||
## High Level
|
||||
|
||||
[What is Mem0?](https://docs.mem0.ai/overview): consider using Mem0, when building conversational AI agents with memory. The page discusses the main reasons to use Mem0: Context Management, Smart Retrieval System, Simple API Integration and Dual Storage Architecture(vector and graph database).
|
||||
[How is Mem0 different from traditional RAG?](https://docs.mem0.ai/faqs#how-mem0-is-different-from-traditional-rag): Mem0's memory for LLMs offers superior entity relationship understanding, contextual continuity, and adaptive learning compared to RAG. It retains information across sessions, dynamically updates with new data, and personalizes interactions, making it ideal for context-aware AI applications.
|
||||
|
||||
## Concepts
|
||||
|
||||
[Memory Types](https://docs.mem0.ai/core-concepts/memory-types): Mem0 implements both short-term memory (for conversation history and immediate context) and long-term memory (for persistent storage of factual, episodic, and semantic information) to maintain context and personalization across interactions.
|
||||
[Memory Operations](https://docs.mem0.ai/core-concepts/memory-operations): Two core operations power Mem0's functionality: `add` Processes and stores conversations through information extraction, conflict resolution, and dual storage and `search` Retrieves relevant memories using semantic search with query processing and result ranking
|
||||
[Information Processing](https://docs.mem0.ai/core-concepts/memory-operations): When adding memories, Mem0 uses LLMs to extract relevant information, identify entities and relationships, and resolve conflicts with existing data.
|
||||
[Storage Architecture](https://docs.mem0.ai/core-concepts/memory-types): Mem0 combines vector embeddings for semantic information storage with efficient retrieval mechanisms, enabling fast access to relevant past interactions while maintaining user-specific context across sessions.
|
||||
|
||||
## How-to guides
|
||||
|
||||
### Installation
|
||||
|
||||
[Mem0 Installation](https://docs.mem0.ai/quickstart): Mem0 offers two installation options: Mem0 Platform (Managed Solution) and Mem0 OSS.
|
||||
[How to: install Mem0 Platform (Managed Solution)](https://docs.mem0.ai/quickstart#mem0-platform-managed-solution): The easiest way to get started with Mem0 is to use the managed platform. This approach eliminates the need to set up and maintain your own infrastructure.
|
||||
[How to: install Mem0 OSS](https://docs.mem0.ai/quickstart#mem0-open-source): If you prefer to manage your own infrastructure, you can install Mem0 OSS. This option requires setting up your own infrastructure and managing your own vector database.
|
||||
|
||||
## Platform
|
||||
|
||||
### Usage
|
||||
|
||||
[Initialize Client](https://docs.mem0.ai/platform/quickstart#3-instantiate-client): Mem0 gives two ways to initialize the client: Synchronous -> MemoryClient and Asynchronous -> AsyncMemoryClient.
|
||||
[How to: add memories](https://docs.mem0.ai/platform/quickstart#4-1-create-memories): Add memories to Mem0 using messages or a simple string. The `add` method allows adding memories to a specific memory by providing `user_id`, `agent_id`, `run_id`, or `app_id`.
|
||||
[How to: search memories](https://docs.mem0.ai/platform/quickstart#4-2-search-memories): Search memories in Mem0 by passing a query string and optional parameters. The `search` method returns a list of memories sorted by relevance. Csutom filters can also be passed to make the search more specific.
|
||||
[How to: get all memories](https://docs.mem0.ai/platform/quickstart#4-4-get-all-memories): Get all the memories by passing a `user_id`, `agent_id`, `run_id`, or `app_id`. Also custom filters can be passed to filter the memories.
|
||||
[How to: get memory history](https://docs.mem0.ai/platform/quickstart#4-5-get-memory-history): Get the history of a specific memory by passing `memory_id` after adding memories using the `add` method.
|
||||
[How to: update memory](https://docs.mem0.ai/platform/quickstart#4-6-update-memory): Update a memory by passing `memory_id` after adding memories using the `add` method.
|
||||
[How to: delete memory](https://docs.mem0.ai/platform/quickstart#4-7-delete-memories): Delete memories by passing `memory_id` after adding memories using the `add` method.
|
||||
[How to: reset client](https://docs.mem0.ai/platform/quickstart#4-8-reset-client): Reset the client where all the memories, users, agents, sessions and runs are deleted.
|
||||
[How to: batch update memories](https://docs.mem0.ai/platform/quickstart#4-9-batch-update-memories): Batch update memories by passing a list of memories to the `batch_update` method.
|
||||
[How to: batch delete memories](https://docs.mem0.ai/platform/quickstart#4-10-batch-delete-memories): Batch delete memories by passing a list of memories to the `batch_delete` method.
|
||||
|
||||
## Features
|
||||
|
||||
[Graph Memory](https://docs.mem0.ai/features/graph-memory): Mem0's graph memory system builds relationships between entities in your data, enabling contextually relevant retrieval by analyzing connections between information points - activate it with `enable_graph=True` to enhance search results beyond direct semantic matches, ideal for applications tracking evolving relationships.
|
||||
[Advanced Retrieval](https://docs.mem0.ai/features/advanced-retrieval): Mem0 offers enhanced search capabilities through three advanced retrieval modes: keyword search (improves recall by matching specific terms), reranking (ensures most relevant results appear first using neural networks), and filtering (narrows results by specific criteria) - each can be enabled independently or in combination to optimize search precision and relevance.
|
||||
[Multimodal Support](https://docs.mem0.ai/features/multimodal-support): Mem0 extends beyond text by supporting images and documents (JPG, PNG, MDX, TXT, PDF), allowing users to integrate visual and document content through direct URLs or Base64 encoding, enhancing the memory system's ability to understand and recall information from various media types.
|
||||
[Memory Customization](https://docs.mem0.ai/features/selective-memory): Mem0 enables selective memory storage through inclusion and exclusion rules, allowing users to focus on relevant information (like specific topics) while omitting irrelevant data (such as food preferences), resulting in more efficient, accurate, and privacy-conscious AI interactions.
|
||||
[Custom Categories](https://docs.mem0.ai/features/custom-categories): Mem0 allows setting custom categories at both project level and during individual API calls, overriding default categories (like personal_details, family, sports) with more specific ones to improve memory categorization accuracy - simply provide a list of category dictionaries with descriptive definitions when adding memories.
|
||||
[Async Client](https://docs.mem0.ai/features/async-client): Mem0 provides an AsyncMemoryClient for non-blocking operations, offering the same functionality as the synchronous client (add, search, get_all, delete, etc.) but with async/await support, making it ideal for high-concurrency applications that need to perform memory operations without blocking execution.
|
||||
[Memory Export](https://docs.mem0.ai/features/memory-export): Mem0 enables exporting memories in structured formats using customizable Pydantic schemas, allowing you to transform stored memories into specific data structures by defining schemas, submitting export jobs with optional processing instructions, and retrieving the formatted data with various filtering options.
|
||||
|
||||
## OSS
|
||||
|
||||
### Usage
|
||||
|
||||
#### Python
|
||||
|
||||
[Initialize python client](https://docs.mem0.ai/open-source/python-quickstart#installation): Install Mem0 with `pip install mem0ai`, then initialize the client with `from mem0 import Memory; m = Memory()` (requires OpenAI API key). For advanced usage, configure with custom parameters or enable graph memory with `Memory(enable_graph=True)`.
|
||||
[Configuration Parameters](https://docs.mem0.ai/open-source/python-quickstart#configuration-parameters): Mem0 offers extensive configuration options for vector stores (provider, host, port), LLMs (provider, model, temperature, API keys), embedders (provider, model), graph stores (provider, URL, credentials), and general settings (history path, API version, custom prompts) - all customizable through a comprehensive configuration dictionary.
|
||||
[How to: add memories](https://docs.mem0.ai/open-source/python-quickstart#store-a-memory): Add memories to Mem0 using the Python OSS client's `add` method with messages or a simple string. This method allows adding memories to a specific memory by providing `user_id`, `agent_id`, `run_id`, or `app_id`.
|
||||
[How to: search memories](https://docs.mem0.ai/open-source/python-quickstart#search-memories): Search memories in Mem0 using the Python OSS client by passing a query string and optional parameters. The `search` method returns a list of memories sorted by relevance. Custom filters can also be passed to make the search more specific.
|
||||
[How to: get all memories](https://docs.mem0.ai/open-source/python-quickstart#retrieve-memories): Get all the memories using the Python OSS client by passing a `user_id`, `agent_id`, `run_id`, or `app_id`. Also custom filters can be passed to filter the memories.
|
||||
[How to: get memory history](https://docs.mem0.ai/open-source/python-quickstart#memory-history): Get the history of a specific memory in the Python OSS client by passing `memory_id` after adding memories using the `add` method.
|
||||
[How to: update memory](https://docs.mem0.ai/open-source/python-quickstart#update-a-memory): Update a memory in the Python OSS client by passing `memory_id` after adding memories using the `add` method.
|
||||
[How to: delete memory](https://docs.mem0.ai/open-source/python-quickstart#delete-memory): Delete memories in the Python OSS client by passing `memory_id` after adding memories using the `add` method.
|
||||
|
||||
#### Node.js
|
||||
|
||||
[Initialize node client](https://docs.mem0.ai/open-source/node-quickstart#installation): Install Mem0 with `npm install mem0ai`, then initialize the client with `import { Memory } from 'mem0ai'; const m = new Memory();` (requires OpenAI API key). For advanced usage, configure with custom parameters or enable graph memory with `new Memory({ enableGraph: true })`.
|
||||
[How to: add memories](https://docs.mem0.ai/open-source/node-quickstart#store-a-memory): Add memories to Mem0 using the Node.js OSS client's `add` method with messages or a simple string. This method allows adding memories to a specific memory by providing `user_id`, `agent_id`, `run_id`, or `app_id`.
|
||||
[How to: search memories](https://docs.mem0.ai/open-source/node-quickstart#search-memories): Search memories in Mem0 using the Node.js OSS client by passing a query string and optional parameters. The `search` method returns a list of memories sorted by relevance. Custom filters can also be passed to make the search more specific.
|
||||
[How to: get all memories](https://docs.mem0.ai/open-source/node-quickstart#retrieve-memories): Get all the memories using the Node.js OSS client by passing a `user_id`, `agent_id`, `run_id`, or `app_id`. Also custom filters can be passed to filter the memories.
|
||||
[How to: get memory history](https://docs.mem0.ai/open-source/node-quickstart#memory-history): Get the history of a specific memory in the Node.js OSS client by passing `memory_id` after adding memories using the `add` method.
|
||||
[How to: update memory](https://docs.mem0.ai/open-source/node-quickstart#update-a-memory): Update a memory in the Node.js OSS client by passing `memory_id` after adding memories using the `add` method.
|
||||
[How to: delete memory](https://docs.mem0.ai/open-source/node-quickstart#delete-memory): Delete memories in the Node.js OSS client by passing `memory_id` after adding memories using the `add` method.
|
||||
|
||||
### Features
|
||||
|
||||
[OpenAI Compatibility](https://docs.mem0.ai/features/openai_compatibility): Mem0 offers seamless integration with OpenAI-compatible APIs, allowing developers to enhance conversational agents with structured memory by initializing with a Mem0 API key (or locally without one), supporting various LLM providers, and enabling personalized responses through user context persistence across interactions with parameters like user_id, agent_id, and custom filters.
|
||||
[Custom Fact Extraction Prompt](https://docs.mem0.ai/features/custom-fact-extraction-prompt): Mem0 enables custom fact extraction prompts to tailor information extraction for specific use cases by defining domain-specific examples and formats, allowing precise control over what information is extracted from messages - simply provide a custom prompt with few-shot examples in the config when initializing the Memory client.
|
||||
[Custom Update Memory Prompt](https://docs.mem0.ai/features/custom-update-memory-prompt): Mem0 enables customizing the update memory prompt to control how memories are modified by comparing newly retrieved facts with existing memories and determining appropriate actions (add, update, delete, or no change) based on custom logic and examples provided in the prompt configuration.
|
||||
[REST API Server](https://docs.mem0.ai/open-source/features/rest-api): Mem0 provides a FastAPI-based REST API server that supports core operations (create/retrieve/search/update/delete memories) with OpenAPI documentation at /docs, easily deployable via Docker Compose with pre-configured databases (postgres pgvector, neo4j) - just set OPENAI_API_KEY to get started.
|
||||
[Graph Memory](https://docs.mem0.ai/open-source/graph_memory/overview): Mem0's open-source graph memory system enables building and querying relationships between entities by installing with `pip install "mem0ai[graph]"` and configuring a graph store provider (like Neo4j) - this allows for more contextual memory retrieval by combining vector and graph-based approaches to track evolving relationships between information points.
|
||||
|
||||
### Components
|
||||
|
||||
#### LLMs
|
||||
|
||||
[OpenAI](https://docs.mem0.ai/components/llms/models/openai): Integrate OpenAI LLM models by setting OPENAI_API_KEY and configuring the Memory client with provider settings - supports both standard models (like gpt-4) and structured-outputs, with options for temperature, max tokens and Openrouter integration.
|
||||
[Anthropic](https://docs.mem0.ai/components/llms/models/anthropic): Integrate Anthropic LLM models by setting ANTHROPIC_API_KEY from your Account Settings Page and configuring the Memory client with provider settings - supports models like claude-3-7-sonnet-latest with customizable temperature and max_tokens parameters.
|
||||
[Google AI](https://docs.mem0.ai/components/llms/models/google_AI): Integrate Gemini LLM models by setting GEMINI_API_KEY from Google Maker Suite and configuring the Memory client with litellm provider - supports models like gemini-pro with customizable temperature and max_tokens parameters.
|
||||
[Groq](https://docs.mem0.ai/components/llms/models/groq): Integrate Groq's Language Processing Unit (LPU) optimized models by setting GROQ_API_KEY and configuring the Memory client with provider settings - supports models like mixtral-8x7b-32768 with customizable temperature and max_tokens parameters for high-performance AI inference.
|
||||
[Together](https://docs.mem0.ai/components/llms/models/together): Integrate Together LLM models by setting TOGETHER_API_KEY and configuring the Memory client with provider settings - supports both standard models (like together-llama-3-8b-instant) and structured-outputs, with options for temperature, max tokens and Openrouter integration.
|
||||
[Deepseek](https://docs.mem0.ai/components/llms/models/deepseek): Integrate Deepseek LLM models by setting DEEPSEEK_API_KEY and configuring the Memory client with provider settings - supports both standard models (like deepseek-chat) and structured-outputs, with options for temperature, max tokens and Openrouter integration.
|
||||
[xAI](https://docs.mem0.ai/components/llms/models/xai): Integrate xAI LLM models by setting XAI_API_KEY and configuring the Memory client with provider settings - supports both standard models (like xai-chat) and structured-outputs, with options for temperature, max tokens and Openrouter integration.
|
||||
[LM Studio](https://docs.mem0.ai/components/llms/models/lmstudio): Run Mem0 locally with LM Studio by configuring the Memory client with provider settings and a local LM Studio server - supports using LM Studio for both LLM inference and embeddings, requiring no external API keys when running fully locally with appropriate models loaded.
|
||||
[Ollama](https://docs.mem0.ai/components/llms/models/ollama): Run Mem0 locally with Ollama LLM models by configuring the Memory client with provider settings like model (e.g. mixtral:8x7b), temperature and max_tokens - supports tool calling and requires only OpenAI API key for embeddings.
|
||||
[AWS Bedrock](https://docs.mem0.ai/components/llms/models/aws_bedrock): Integrate AWS Bedrock LLM models by setting AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and configuring the Memory client with provider settings - supports both standard models (like bedrock-anthropic-claude-3-5-sonnet) and structured-outputs, with options for temperature, max tokens and Openrouter integration.
|
||||
[Azure OpenAI](https://docs.mem0.ai/components/llms/models/azure_openai): Integrate Azure OpenAI LLM models by setting LLM_AZURE_OPENAI_API_KEY, LLM_AZURE_ENDPOINT, LLM_AZURE_DEPLOYMENT and LLM_AZURE_API_VERSION environment variables and configuring the Memory client with provider settings - supports both standard and structured-output models with customizable deployment, API version, endpoint and headers (note: some features like parallel tool calling and temperature are currently unsupported).
|
||||
[LiteLLM](https://docs.mem0.ai/components/llms/models/litellm): Integrate LiteLLM LLM models by setting LITELLM_API_KEY and configuring the Memory client with provider settings - supports both standard models (like llama3.1:8b) and structured-outputs, with options for temperature, max tokens and Openrouter integration.
|
||||
[Mistral](https://docs.mem0.ai/components/llms/models/mistral): Integrate Mistral LLM models by setting MISTRAL_API_KEY and configuring the Memory client with provider settings - supports both standard models (like mistral-large-latest) and structured-outputs, with options for temperature, max tokens and Openrouter integration.
|
||||
|
||||
#### Embedders
|
||||
|
||||
[OpenAI](https://docs.mem0.ai/components/embedders/models/openai): Integrate OpenAI embedding models by setting OPENAI_API_KEY and configuring the Memory client with provider settings - supports models like text-embedding-3-small (default) and text-embedding-3-large with customizable dimensions.
|
||||
[Azure OpenAI](https://docs.mem0.ai/components/embedders/models/azure_openai): Integrate Azure OpenAI embedding models by setting EMBEDDING_AZURE_OPENAI_API_KEY, EMBEDDING_AZURE_ENDPOINT, EMBEDDING_AZURE_DEPLOYMENT and EMBEDDING_AZURE_API_VERSION environment variables and configuring the Memory client with provider settings - supports models like text-embedding-3-large with customizable dimensions and Azure-specific configurations through azure_kwargs.
|
||||
[Vertex AI](https://docs.mem0.ai/components/embedders/models/google_ai): Integrate Google Cloud's Vertex AI embedding models by setting GOOGLE_APPLICATION_CREDENTIALS environment variable to your service account credentials JSON file and configuring the Memory client with provider settings - supports models like text-embedding-004 with customizable embedding types (RETRIEVAL_DOCUMENT, RETRIEVAL_QUERY, etc.) and dimensions.
|
||||
[Groq](https://docs.mem0.ai/components/embedders/models/groq): Integrate Groq embedding models by setting GROQ_API_KEY and configuring the Memory client with provider settings - supports models like text-embedding-3-small (default) and text-embedding-3-large with customizable dimensions.
|
||||
[Hugging Face](https://docs.mem0.ai/components/embedders/models/hugging_face): Run Mem0 locally with Hugging Face embedding models by configuring the Memory client with provider settings like model (e.g. multi-qa-MiniLM-L6-cos-v1), embedding dimensions and model_kwargs - requires only OpenAI API key for LLM functionality.
|
||||
[Ollama](https://docs.mem0.ai/components/embedders/models/ollama): Run Mem0 locally with Ollama embedding models by configuring the Memory client with provider settings like model (e.g. nomic-embed-text), embedding dimensions (default 512) and custom base URL - requires only OpenAI API key for LLM functionality.
|
||||
[Gemini](https://docs.mem0.ai/components/embedders/models/gemini): Integrate Gemini embedding models by setting GOOGLE_API_KEY and configuring the Memory client with provider settings - supports models like text-embedding-004 with customizable dimensions (default 768) and requires OpenAI API key for LLM functionality.
|
||||
|
||||
#### Vector Stores
|
||||
|
||||
[Qdrant](https://docs.mem0.ai/components/vectordbs/dbs/qdrant): Integrate Qdrant vector database by configuring the Memory client with provider settings like collection_name, host, port, and other parameters - supports both local and remote deployments with options for persistent storage and custom client configurations.
|
||||
[Pinecone](https://docs.mem0.ai/components/vectordbs/dbs/pinecone): Integrate Pinecone's managed vector database by configuring the Memory client with serverless or pod deployment options, supporting high-performance vector search with customizable embedding dimensions, distance metrics, and cloud providers (AWS/GCP/Azure) - requires PINECONE_API_KEY and matching embedding model dimensions (e.g. 1536 for OpenAI).
|
||||
[Milvus](https://docs.mem0.ai/components/vectordbs/dbs/milvus): Integrate Milvus open-source vector database by configuring the Memory client with provider settings like url (default localhost:19530), token (for Zilliz cloud), collection_name, embedding_model_dims (default 1536) and metric_type - supports both local and cloud deployments for AI applications of any scale.
|
||||
[Weaviate](https://docs.mem0.ai/components/vectordbs/dbs/weaviate): Integrate Weaviate open-source vector search engine by configuring the Memory client with provider settings like collection_name (default: mem0), cluster_url, auth_client_secret and embedding_model_dims (default: 1536) - enables efficient storage and retrieval of high-dimensional vector embeddings.
|
||||
[Chroma](https://docs.mem0.ai/components/vectordbs/dbs/chroma): Integrate Chroma AI-native open-source vector database by configuring the Memory client with provider settings like collection_name (default: mem0), path (default: db), host, port, and client - enables simple storage and search of embeddings with focus on speed and ease of use.
|
||||
[Faiss](https://docs.mem0.ai/components/vectordbs/dbs/faiss): Integrate Faiss, a high-performance library for similarity search and clustering of dense vectors, by configuring the Memory client with settings like collection_name, path, and distance_strategy (euclidean/cosine/inner_product) - supports efficient local vector search with in-memory or persistent storage options and is optimized for large-scale production use.
|
||||
[PGVector](https://docs.mem0.ai/components/vectordbs/dbs/pgvector): Integrate Postgres vector similarity search by configuring the Memory client with database connection settings (user, password, host, port), collection name, embedding dimensions and indexing options (diskann/hnsw) - requires creating vector extension in Postgres and supports both local and cloud deployments.
|
||||
[Elasticsearch](https://docs.mem0.ai/components/vectordbs/dbs/elasticsearch): Integrate Elasticsearch vector database by configuring host, port, collection name and authentication settings - supports k-NN vector search, cloud/local deployments, custom search queries, and requires `pip install elasticsearch>=8.0.0`.
|
||||
[Redis](https://docs.mem0.ai/components/vectordbs/dbs/redis): Integrate Redis vector database for real-time vector storage and search by configuring collection name, embedding dimensions (default 1536), and Redis URL - supports both local Docker deployment and remote Redis Stack instances.
|
||||
[Supabase](https://docs.mem0.ai/components/vectordbs/dbs/supabase): Integrate Supabase's PostgreSQL database with pgvector extension by configuring connection string, collection name, and optional index settings (hnsw/ivfflat) - enables efficient vector similarity search with support for different distance measures (cosine/l2/l1) and requires SQL migrations to enable vector functionality.
|
||||
[Azure AI Search](https://docs.mem0.ai/components/vectordbs/dbs/azure): Integrate Azure AI Search (formerly Azure Cognitive Search) by configuring service_name, api_key and collection_name - supports vector compression (none/scalar/binary), hybrid search modes, and customizable vector dimensions with automatic extraction of filterable fields like user_id.
|
||||
[Vertex AI Search](https://docs.mem0.ai/components/vectordbs/dbs/vertex_ai): Integrate Google Cloud's Vertex AI Vector Search by configuring endpoint_id, index_id, deployment_index_id, project details and optional region/credentials - enables efficient vector similarity search through Google Cloud's managed service with support for both get and search operations.
|
||||
@@ -7,7 +7,7 @@ iconType: "solid"
|
||||
Mem0 provides a REST API server (written using FastAPI). Users can perform all operations through REST endpoints. The API also includes OpenAPI documentation, accessible at `/docs` when the server is running.
|
||||
|
||||
<Frame caption="APIs supported by Mem0 REST API Server">
|
||||
<img src="/images/rest-api-server.png" />
|
||||
<img src="/images/rest-api-server.png"/>
|
||||
</Frame>
|
||||
|
||||
## Features
|
||||
@@ -23,67 +23,90 @@ Mem0 provides a REST API server (written using FastAPI). Users can perform all o
|
||||
## Running Locally
|
||||
|
||||
<Tabs>
|
||||
<Tab title="With Docker">
|
||||
<Tab title="With Docker Compose">
|
||||
The Development Docker Compose comes pre-configured with postgres pgvector, neo4j and a `server/history/history.db` volume for the history database.
|
||||
|
||||
1. Create a `.env` file in the current directory and set your environment variables. For example:
|
||||
The only required environment variable to run the server is `OPENAI_API_KEY`.
|
||||
|
||||
```txt
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
1. Create a `.env` file in the `server/` directory and set your environment variables. For example:
|
||||
|
||||
2. Either pull the docker image from docker hub or build the docker image locally.
|
||||
```txt
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Pull from Docker Hub">
|
||||
2. Run the Docker container using Docker Compose:
|
||||
|
||||
```bash
|
||||
docker pull mem0/mem0-api-server
|
||||
```
|
||||
```bash
|
||||
cd server
|
||||
docker compose up
|
||||
```
|
||||
|
||||
</Tab>
|
||||
3. Access the API at http://localhost:8888.
|
||||
|
||||
<Tab title="Build Locally">
|
||||
4. Making changes to the server code or the library code will automatically reload the server.
|
||||
</Tab>
|
||||
|
||||
```bash
|
||||
docker build -t mem0-api-server .
|
||||
```
|
||||
<Tab title="With Docker">
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
1. Create a `.env` file in the current directory and set your environment variables. For example:
|
||||
|
||||
3. Run the Docker container:
|
||||
```txt
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
|
||||
``` bash
|
||||
docker run -p 8000:8000 mem0-api-server --env-file .env
|
||||
```
|
||||
2. Either pull the docker image from docker hub or build the docker image locally.
|
||||
|
||||
4. Access the API at http://localhost:8000.
|
||||
<Tabs>
|
||||
<Tab title="Pull from Docker Hub">
|
||||
|
||||
</Tab>
|
||||
```bash
|
||||
docker pull mem0/mem0-api-server
|
||||
```
|
||||
|
||||
<Tab title="Without Docker">
|
||||
</Tab>
|
||||
|
||||
1. Create a `.env` file in the current directory and set your environment variables. For example:
|
||||
<Tab title="Build Locally">
|
||||
|
||||
```txt
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
```bash
|
||||
docker build -t mem0-api-server .
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
3. Run the Docker container:
|
||||
|
||||
3. Start the FastAPI server:
|
||||
``` bash
|
||||
docker run -p 8000:8000 mem0-api-server --env-file .env
|
||||
```
|
||||
|
||||
```bash
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
4. Access the API at http://localhost:8000.
|
||||
|
||||
4. Access the API at http://localhost:8000.
|
||||
</Tab>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Without Docker">
|
||||
|
||||
1. Create a `.env` file in the current directory and set your environment variables. For example:
|
||||
|
||||
```txt
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. Start the FastAPI server:
|
||||
|
||||
```bash
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
|
||||
4. Access the API at http://localhost:8000.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Usage
|
||||
|
||||
+7
-5
@@ -1391,11 +1391,11 @@
|
||||
"x-code-samples": [
|
||||
{
|
||||
"lang": "Python",
|
||||
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nquery = \"Your search query here\"\n\nresults = client.search(query, user_id=\"<user_id>\", output_format=\"v1.0\")\nprint(results)"
|
||||
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nquery = \"Your search query here\"\n\nresults = client.search(query, user_id=\"<user_id>\", output_format=\"v1.1\")\nprint(results)"
|
||||
},
|
||||
{
|
||||
"lang": "JavaScript",
|
||||
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\nconst query = \"Your search query here\";\n\nclient.search(query, { user_id: \"<user_id>\", output_format: \"v1.0\" })\n .then(result => console.log(result))\n .catch(error => console.error(error));"
|
||||
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\nconst query = \"Your search query here\";\n\nclient.search(query, { user_id: \"<user_id>\", output_format: \"v1.1\" })\n .then(result => console.log(result))\n .catch(error => console.error(error));"
|
||||
},
|
||||
{
|
||||
"lang": "cURL",
|
||||
@@ -4893,10 +4893,11 @@
|
||||
"default": true
|
||||
},
|
||||
"output_format": {
|
||||
"description": "It two output formats: `v1.0` (default) and `v1.1`. To enable the latest format, which provides enhanced detail for each memory operation, set the output_format parameter to `v1.1`. Note that `v1.0` will be deprecated in version 0.1.35.",
|
||||
"description": "It two output formats: `v1.0` (default) and `v1.1`. We recommend using `v1.1` as `v1.0` will be deprecated soon.",
|
||||
"title": "Output format",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
"nullable": true,
|
||||
"default": "v1.0"
|
||||
},
|
||||
"custom_categories": {
|
||||
"description": "A list of categories with category name and it's description.",
|
||||
@@ -5021,7 +5022,8 @@
|
||||
"title": "Output format",
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "The search method supports two output formats: `v1.0` (default) and `v1.1`."
|
||||
"default": "v1.0",
|
||||
"description": "The search method supports two output formats: `v1.0` (default) and `v1.1`. We recommend using `v1.1` as `v1.0` will be deprecated soon."
|
||||
},
|
||||
"org_id": {
|
||||
"title": "Organization id",
|
||||
|
||||
+111
-330
@@ -86,11 +86,7 @@ messages = [
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
]
|
||||
|
||||
# The default output_format is v1.0
|
||||
client.add(messages, user_id="alex", output_format="v1.0", version="v2")
|
||||
|
||||
# To use the latest output_format, set the output_format parameter to "v1.1"
|
||||
client.add(messages, user_id="alex", output_format="v1.1", metadata={"food": "vegan"}, version="v2")
|
||||
client.add(messages, user_id="alex", metadata={"food": "vegan"})
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
@@ -98,7 +94,7 @@ const messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
];
|
||||
client.add(messages, { user_id: "alex", output_format: "v1.1", metadata: { food: "vegan" }, version: "v2" })
|
||||
client.add(messages, { user_id: "alex", metadata: { food: "vegan" } })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
@@ -113,40 +109,13 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
],
|
||||
"user_id": "alex",
|
||||
"output_format": "v1.1",
|
||||
"metadata": {
|
||||
"food": "vegan"
|
||||
},
|
||||
"version": "v2"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output (v1.0)
|
||||
[
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-4g7h-8i9j-k0l1m2n3o4p5",
|
||||
"data": {
|
||||
"memory": "Name is Alex"
|
||||
},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "b2c3d4e5-f6g7-8h9i-j0k1-l2m3n4o5p6q7",
|
||||
"data": {
|
||||
"memory": "Is a vegetarian"
|
||||
},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "c3d4e5f6-g7h8-9i0j-k1l2-m3n4o5p6q7r8",
|
||||
"data": {
|
||||
"memory": "Is allergic to nuts"
|
||||
},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
```
|
||||
```json Output (v1.1)
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
@@ -167,9 +136,6 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
<Note> The `add` method offers support for two output formats: `v1.0` (default) and `v1.1`. To enable the latest format, which provides enhanced detail for each memory operation, set the `output_format` parameter to `v1.1`. </Note>
|
||||
|
||||
<Note>
|
||||
Messages passed along with `user_id`, `run_id`, or `app_id` are stored as user memories, while messages from the assistant are excluded from memory. To store messages for the assistant, use `agent_id` exclusively and avoid including other IDs, such as user_id, alongside it. This ensures the memory is properly attributed to the assistant.
|
||||
</Note>
|
||||
@@ -191,11 +157,7 @@ messages = [
|
||||
{"role": "assistant", "content": "Great! I'll remember that you're interested in vegetarian restaurants in Tokyo for your upcoming trip. I'll prepare a list for you in our next interaction."}
|
||||
]
|
||||
|
||||
# The default output_format is v1.0
|
||||
client.add(messages, user_id="alex", run_id="trip-planning-2024", output_format="v1.0", version="v2")
|
||||
|
||||
# To use the latest output_format, set the output_format parameter to "v1.1"
|
||||
client.add(messages, user_id="alex", run_id="trip-planning-2024", output_format="v1.1", version="v2")
|
||||
client.add(messages, user_id="alex", run_id="trip-planning-2024")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
@@ -205,7 +167,7 @@ const messages = [
|
||||
{"role": "user", "content": "Yes, please! Especially in Tokyo."},
|
||||
{"role": "assistant", "content": "Great! I'll remember that you're interested in vegetarian restaurants in Tokyo for your upcoming trip. I'll prepare a list for you in our next interaction."}
|
||||
];
|
||||
client.add(messages, { user_id: "alex", run_id: "trip-planning-2024", output_format: "v1.1", version: "v2" })
|
||||
client.add(messages, { user_id: "alex", run_id: "trip-planning-2024" })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
@@ -222,32 +184,11 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
{"role": "assistant", "content": "Great! I'll remember that you're interested in vegetarian restaurants in Tokyo for your upcoming trip. I'll prepare a list for you in our next interaction."}
|
||||
],
|
||||
"user_id": "alex",
|
||||
"run_id": "trip-planning-2024",
|
||||
"output_format": "v1.1",
|
||||
"version": "v2"
|
||||
"run_id": "trip-planning-2024"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output (v1.0)
|
||||
[
|
||||
{
|
||||
"id": "f2968654-5cd8-4d58-9f40-57ee339846b6",
|
||||
"data": {
|
||||
"memory": "Interested in vegetarian restaurants in Tokyo"
|
||||
},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "f2968654-5cd8-4d58-9f40-57ee339846b6",
|
||||
"data": {
|
||||
"memory": "Planning a trip to Japan next month"
|
||||
},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json Output (v1.1)
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
@@ -275,11 +216,7 @@ messages = [
|
||||
{"role": "assistant", "content": "Understood. I'm an AI tutor with a personality. My name is Alice."}
|
||||
]
|
||||
|
||||
# The default output_format is v1.0
|
||||
client.add(messages, agent_id="ai-tutor", output_format="v1.0", version="v2")
|
||||
|
||||
# To use the latest output_format, set the output_format parameter to "v1.1"
|
||||
client.add(messages, agent_id="ai-tutor", output_format="v1.1", version="v2")
|
||||
client.add(messages, agent_id="ai-tutor")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
@@ -287,7 +224,7 @@ const messages = [
|
||||
{"role": "system", "content": "You are an AI tutor with a personality. Give yourself a name for the user."},
|
||||
{"role": "assistant", "content": "Understood. I'm an AI tutor with a personality. My name is Alice."}
|
||||
];
|
||||
client.add(messages, { agent_id: "ai-tutor", output_format: "v1.1", version: "v2" })
|
||||
client.add(messages, { agent_id: "ai-tutor" })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
@@ -301,39 +238,11 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
{"role": "system", "content": "You are an AI tutor with a personality. Give yourself a name for the user."},
|
||||
{"role": "assistant", "content": "Understood. I'm an AI tutor with a personality. My name is Alice."}
|
||||
],
|
||||
"agent_id": "ai-tutor",
|
||||
"output_format": "v1.1",
|
||||
"version": "v2"
|
||||
"agent_id": "ai-tutor"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output (v1.0)
|
||||
[
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-4g7h-8i9j-k0l1m2n3o4p5",
|
||||
"data": {
|
||||
"memory": "Name is Alex"
|
||||
},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "b2c3d4e5-f6g7-8h9i-j0k1-l2m3n4o5p6q7",
|
||||
"data": {
|
||||
"memory": "Is a vegetarian"
|
||||
},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "c3d4e5f6-g7h8-9i0j-k1l2-m3n4o5p6q7r8",
|
||||
"data": {
|
||||
"memory": "Is allergic to nuts"
|
||||
},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json Output (v1.1)
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
@@ -371,7 +280,7 @@ messages = [
|
||||
{"role": "assistant", "content": "That's great! I'm going to Dubai next month."},
|
||||
]
|
||||
|
||||
client.add(messages=messages, user_id="user1", agent_id="agent1", version="v2")
|
||||
client.add(messages=messages, user_id="user1", agent_id="agent1")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
@@ -380,7 +289,7 @@ const messages = [
|
||||
{"role": "assistant", "content": "That's great! I'm going to Dubai next month."},
|
||||
]
|
||||
|
||||
client.add(messages, { user_id: "user1", agent_id: "agent1", version: "v2" })
|
||||
client.add(messages, { user_id: "user1", agent_id: "agent1" })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
@@ -395,23 +304,25 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
{"role": "assistant", "content": "That's great! I'm going to Dubai next month."},
|
||||
],
|
||||
"user_id": "user1",
|
||||
"agent_id": "agent1",
|
||||
"version": "v2"
|
||||
"agent_id": "agent1"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
'id': 'c57abfa2-f0ac-48af-896a-21728dbcecee0',
|
||||
'data': {'memory': 'Travelling to San Francisco'},
|
||||
'event': 'ADD'
|
||||
},
|
||||
{ 'id': '0e8c003f-7db7-426a-9fdc-a46f9331a0c2',
|
||||
'data': {'memory': 'Going to Dubai next month'},
|
||||
'event': 'ADD'
|
||||
}
|
||||
]
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "c57abfa2-f0ac-48af-896a-21728dbcecee0",
|
||||
"data": {"memory": "Travelling to San Francisco"},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "0e8c003f-7db7-426a-9fdc-a46f9331a0c2",
|
||||
"data": {"memory": "Going to Dubai next month"},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
@@ -483,15 +394,17 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-4g7h-8i9j-k0l1m2n3o4p5",
|
||||
"data": {
|
||||
"memory": "In San Francisco until August 31st"
|
||||
},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-4g7h-8i9j-k0l1m2n3o4p5",
|
||||
"data": {
|
||||
"memory": "In San Francisco until August 31st"
|
||||
},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
@@ -519,11 +432,7 @@ Pass user messages, interactions, and queries into our search method to retrieve
|
||||
```python Python
|
||||
query = "What should I cook for dinner today?"
|
||||
|
||||
# The default output_format is v1.0
|
||||
client.search(query, user_id="alex", output_format="v1.0")
|
||||
|
||||
# To use the latest output_format, set the output_format parameter to "v1.1"
|
||||
client.search(query, user_id="alex", output_format="v1.1")
|
||||
client.search(query, user_id="alex")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
@@ -544,23 +453,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/" \
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output (v1.0)
|
||||
[
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json Output (v1.1)
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
@@ -608,19 +501,21 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -699,19 +594,21 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -765,19 +662,21 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -840,19 +739,21 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "654fee-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "654fee-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
@@ -936,48 +837,13 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&page=1&page_size=50"
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output (v1.0)
|
||||
{
|
||||
"count": 204,
|
||||
"next": "https://api.mem0.ai/v1/memories/?user_id=alex&page=2&page_size=50",
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id":"f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory":"是素食主义者,对坚果过敏。",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories":None
|
||||
},
|
||||
{
|
||||
"id":"0a14d8f0-e364-4f5c-b305-10da1f0d0878",
|
||||
"memory":"Will maintain personalized travel preferences for each user. Provide customized recommendations based on dietary restrictions, interests, and past interactions.",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":"None",
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at":"2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at":"2024-07-26T00:31:03.543778-07:00",
|
||||
"categories":None
|
||||
}
|
||||
... (remaining 48 memories)
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```json Output (v1.1)
|
||||
{
|
||||
"count": 204,
|
||||
"next": "https://api.mem0.ai/v1/memories/?user_id=alex&output_format=v1.1&page=2&page_size=50",
|
||||
"previous": null,
|
||||
"results": {
|
||||
"results": [
|
||||
"results":
|
||||
[
|
||||
{
|
||||
"id":"f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory":"是素食主义者,对坚果过敏。",
|
||||
@@ -1003,8 +869,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&page=1&page_size=50"
|
||||
"categories":None
|
||||
}
|
||||
... (remaining 48 memories)
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1029,48 +894,13 @@ curl -X GET "https://api.mem0.ai/v1/memories/?agent_id=ai-tutor&page=1&page_size
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output (v1.0)
|
||||
{
|
||||
"count": 78,
|
||||
"next": "https://api.mem0.ai/v1/memories/?agent_id=ai-tutor&page=2&page_size=50",
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id":"f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory":"是素食主义者,对坚果过敏。",
|
||||
"agent_id":"ai-tutor",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories":None
|
||||
},
|
||||
{
|
||||
"id":"0a14d8f0-e364-4f5c-b305-10da1f0d0878",
|
||||
"memory":"My name is Alice.",
|
||||
"agent_id":"ai-tutor",
|
||||
"hash":"35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at":"2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at":"2024-07-26T00:31:03.543778-07:00",
|
||||
"categories":None
|
||||
}
|
||||
... (remaining 48 memories)
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```json Output (v1.1)
|
||||
{
|
||||
"count": 78,
|
||||
"next": "https://api.mem0.ai/v1/memories/?agent_id=ai-tutor&output_format=v1.1&page=2&page_size=50",
|
||||
"previous": null,
|
||||
"results": {
|
||||
"results": [
|
||||
"results":
|
||||
[
|
||||
{
|
||||
"id": "f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory": "是素食主义者,对坚果过敏。",
|
||||
@@ -1094,8 +924,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?agent_id=ai-tutor&page=1&page_size
|
||||
"updated_at": "2024-07-26T00:31:03.543778-07:00"
|
||||
}
|
||||
... (remaining 48 memories)
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -1119,60 +948,13 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&run_id=trip-planning-
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output (v1.0)
|
||||
```json Output
|
||||
{
|
||||
"count": 18,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id":"06d8df63-7bd2-4fad-9acb-60871bcecee0",
|
||||
"memory":"Planning a trip to Japan next month. Interested in vegetarian restaurants in Tokyo.",
|
||||
"user_id":"alex",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at":"2024-07-26T00:25:16.566471-07:00",
|
||||
"updated_at":"2024-07-26T00:25:16.566492-07:00",
|
||||
"categories":None
|
||||
},
|
||||
{
|
||||
"id":"b4229775-d860-4ccb-983f-0f628ca112f5",
|
||||
"memory":"Planning a trip to Japan next month. Interested in vegetarian restaurants in Tokyo.",
|
||||
"user_id":"alex",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at":"2024-07-26T00:33:20.350542-07:00",
|
||||
"updated_at":"2024-07-26T00:33:20.350560-07:00",
|
||||
"categories":None
|
||||
},
|
||||
{
|
||||
"id":"df1aca24-76cf-4b92-9f58-d03857efcb64",
|
||||
"memory":"Planning a trip to Japan next month. Interested in vegetarian restaurants in Tokyo.",
|
||||
"user_id":"alex",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at":"2024-07-26T00:51:09.642275-07:00",
|
||||
"updated_at":"2024-07-26T00:51:09.642295-07:00",
|
||||
"categories":None
|
||||
}
|
||||
... (remaining 15 memories)
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```json Output (v1.1)
|
||||
{
|
||||
"count": 18,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": {
|
||||
"results": [
|
||||
"results":
|
||||
[
|
||||
{
|
||||
"id": "06d8df63-7bd2-4fad-9acb-60871bcecee0",
|
||||
"memory": "Planning a trip to Japan next month. Interested in vegetarian restaurants in Tokyo.",
|
||||
@@ -1211,7 +993,6 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&run_id=trip-planning-
|
||||
}
|
||||
... (remaining 15 memories)
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -70,7 +70,7 @@ const retrieveMemories = (memories: any) => {
|
||||
export async function POST(req: Request) {
|
||||
const { messages, system, tools, userId } = await req.json();
|
||||
|
||||
const memories = await getMemories(messages, { user_id: userId });
|
||||
const memories = await getMemories(messages, { user_id: userId, rerank: true, threshold: 0.1 });
|
||||
const mem0Instructions = retrieveMemories(memories);
|
||||
|
||||
const result = streamText({
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"@assistant-ui/react": "^0.8.2",
|
||||
"@assistant-ui/react-ai-sdk": "^0.8.0",
|
||||
"@assistant-ui/react-markdown": "^0.8.0",
|
||||
"@mem0/vercel-ai-provider": "^0.0.14",
|
||||
"@mem0/vercel-ai-provider": "^1.0.0",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.6",
|
||||
"@radix-ui/react-avatar": "^1.1.3",
|
||||
"@radix-ui/react-popover": "^1.1.6",
|
||||
@@ -50,5 +50,10 @@
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"packageManager": "pnpm@10.5.2"
|
||||
"packageManager": "pnpm@10.5.2",
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"sqlite3"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mem0ai",
|
||||
"version": "2.1.12",
|
||||
"version": "2.1.13",
|
||||
"description": "The Memory Layer For Your AI Apps",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
|
||||
@@ -97,7 +97,6 @@ export default class MemoryClient {
|
||||
});
|
||||
|
||||
this._validateApiKey();
|
||||
this._validateOrgProject();
|
||||
|
||||
// Initialize with a temporary ID that will be updated
|
||||
this.telemetryId = "";
|
||||
@@ -109,12 +108,20 @@ export default class MemoryClient {
|
||||
private async _initializeClient() {
|
||||
try {
|
||||
// Generate telemetry ID
|
||||
this.telemetryId = generateHash(this.apiKey);
|
||||
await this.ping();
|
||||
|
||||
if (!this.telemetryId) {
|
||||
this.telemetryId = generateHash(this.apiKey);
|
||||
}
|
||||
|
||||
this._validateOrgProject();
|
||||
|
||||
// Capture initialization event
|
||||
await captureClientEvent("init", this, {
|
||||
captureClientEvent("init", this, {
|
||||
api_version: "v1",
|
||||
client_type: "MemoryClient",
|
||||
}).catch((error: any) => {
|
||||
console.error("Failed to capture event:", error);
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error("Failed to initialize client:", error);
|
||||
@@ -171,10 +178,31 @@ export default class MemoryClient {
|
||||
);
|
||||
}
|
||||
|
||||
async ping(): Promise<void> {
|
||||
const response = await fetch(`${this.host}/v1/ping/`, {
|
||||
headers: {
|
||||
Authorization: `Token ${this.apiKey}`,
|
||||
},
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.status !== "ok") {
|
||||
throw new Error("API Key is invalid");
|
||||
}
|
||||
|
||||
const { org_id, project_id, user_email } = data;
|
||||
|
||||
this.organizationId = org_id || null;
|
||||
this.projectId = project_id || null;
|
||||
this.telemetryId = user_email || "";
|
||||
}
|
||||
|
||||
async add(
|
||||
messages: string | Array<Message>,
|
||||
options: MemoryOptions = {},
|
||||
): Promise<Array<Memory>> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
if (this.organizationName != null && this.projectName != null) {
|
||||
options.org_name = this.organizationName;
|
||||
@@ -211,6 +239,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async update(memoryId: string, message: string): Promise<Array<Memory>> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
const payload = {
|
||||
text: message,
|
||||
@@ -231,6 +260,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async get(memoryId: string): Promise<Memory> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("get", []);
|
||||
return this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/${memoryId}/`,
|
||||
@@ -241,6 +271,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async getAll(options?: SearchOptions): Promise<Array<Memory>> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
const payloadKeys = Object.keys(options || {});
|
||||
this._captureEvent("get_all", [payloadKeys]);
|
||||
@@ -288,6 +319,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async search(query: string, options?: SearchOptions): Promise<Array<Memory>> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
const payloadKeys = Object.keys(options || {});
|
||||
this._captureEvent("search", [payloadKeys]);
|
||||
@@ -319,6 +351,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async delete(memoryId: string): Promise<{ message: string }> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("delete", []);
|
||||
return this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/${memoryId}/`,
|
||||
@@ -330,6 +363,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async deleteAll(options: MemoryOptions = {}): Promise<{ message: string }> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
const payloadKeys = Object.keys(options || {});
|
||||
this._captureEvent("delete_all", [payloadKeys]);
|
||||
@@ -358,6 +392,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async history(memoryId: string): Promise<Array<MemoryHistory>> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("history", []);
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/${memoryId}/history/`,
|
||||
@@ -369,6 +404,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async users(): Promise<AllUsers> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
this._captureEvent("users", []);
|
||||
const options: MemoryOptions = {};
|
||||
@@ -399,6 +435,7 @@ export default class MemoryClient {
|
||||
entityId: string,
|
||||
entity: { type: string } = { type: "user" },
|
||||
): Promise<{ message: string }> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("delete_user", []);
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/entities/${entity.type}/${entityId}/`,
|
||||
@@ -411,6 +448,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async deleteUsers(): Promise<{ message: string }> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
this._captureEvent("delete_users", []);
|
||||
const entities = await this.users();
|
||||
@@ -437,6 +475,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async batchUpdate(memories: Array<MemoryUpdateBody>): Promise<string> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("batch_update", []);
|
||||
const memoriesBody = memories.map((memory) => ({
|
||||
memory_id: memory.memoryId,
|
||||
@@ -454,6 +493,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async batchDelete(memories: Array<string>): Promise<string> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("batch_delete", []);
|
||||
const memoriesBody = memories.map((memory) => ({
|
||||
memory_id: memory,
|
||||
@@ -470,6 +510,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async getProject(options: ProjectOptions): Promise<ProjectResponse> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
const payloadKeys = Object.keys(options || {});
|
||||
this._captureEvent("get_project", [payloadKeys]);
|
||||
@@ -496,6 +537,7 @@ export default class MemoryClient {
|
||||
async updateProject(
|
||||
prompts: PromptUpdatePayload,
|
||||
): Promise<Record<string, any>> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._validateOrgProject();
|
||||
this._captureEvent("update_project", []);
|
||||
if (!(this.organizationId && this.projectId)) {
|
||||
@@ -517,6 +559,7 @@ export default class MemoryClient {
|
||||
|
||||
// WebHooks
|
||||
async getWebhooks(data?: { projectId?: string }): Promise<Array<Webhook>> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("get_webhooks", []);
|
||||
const project_id = data?.projectId || this.projectId;
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
@@ -529,6 +572,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async createWebhook(webhook: WebhookPayload): Promise<Webhook> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("create_webhook", []);
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/api/v1/webhooks/projects/${this.projectId}/`,
|
||||
@@ -542,6 +586,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async updateWebhook(webhook: WebhookPayload): Promise<{ message: string }> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("update_webhook", []);
|
||||
const project_id = webhook.projectId || this.projectId;
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
@@ -561,6 +606,7 @@ export default class MemoryClient {
|
||||
async deleteWebhook(data: {
|
||||
webhookId: string;
|
||||
}): Promise<{ message: string }> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
this._captureEvent("delete_webhook", []);
|
||||
const webhook_id = data.webhookId || data;
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
@@ -574,6 +620,7 @@ export default class MemoryClient {
|
||||
}
|
||||
|
||||
async feedback(data: FeedbackPayload): Promise<{ message: string }> {
|
||||
if (this.telemetryId === "") await this.ping();
|
||||
const payloadKeys = Object.keys(data || {});
|
||||
this._captureEvent("feedback", [payloadKeys]);
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.18.0",
|
||||
"@google/genai": "^0.7.0",
|
||||
"@qdrant/js-client-rest": "^1.13.0",
|
||||
"@types/node": "^20.11.19",
|
||||
"@types/pg": "^8.11.0",
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { GoogleGenAI } from "@google/genai";
|
||||
import { Embedder } from "./base";
|
||||
import { EmbeddingConfig } from "../types";
|
||||
|
||||
export class GoogleEmbedder implements Embedder {
|
||||
private google: GoogleGenAI;
|
||||
private model: string;
|
||||
|
||||
constructor(config: EmbeddingConfig) {
|
||||
this.google = new GoogleGenAI({ apiKey: config.apiKey });
|
||||
this.model = config.model || "text-embedding-004";
|
||||
}
|
||||
|
||||
async embed(text: string): Promise<number[]> {
|
||||
const response = await this.google.models.embedContent({
|
||||
model: this.model,
|
||||
contents: text,
|
||||
config: { outputDimensionality: 768 },
|
||||
});
|
||||
return response.embeddings![0].values!;
|
||||
}
|
||||
|
||||
async embedBatch(texts: string[]): Promise<number[][]> {
|
||||
const response = await this.google.models.embedContent({
|
||||
model: this.model,
|
||||
contents: texts,
|
||||
config: { outputDimensionality: 768 },
|
||||
});
|
||||
return response.embeddings!.map((item) => item.values!);
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,10 @@ export * from "./types";
|
||||
export * from "./embeddings/base";
|
||||
export * from "./embeddings/openai";
|
||||
export * from "./embeddings/ollama";
|
||||
export * from "./embeddings/google";
|
||||
export * from "./llms/base";
|
||||
export * from "./llms/openai";
|
||||
export * from "./llms/google";
|
||||
export * from "./llms/openai_structured";
|
||||
export * from "./llms/anthropic";
|
||||
export * from "./llms/groq";
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { GoogleGenAI } from "@google/genai";
|
||||
import { LLM, LLMResponse } from "./base";
|
||||
import { LLMConfig, Message } from "../types";
|
||||
|
||||
export class GoogleLLM implements LLM {
|
||||
private google: GoogleGenAI;
|
||||
private model: string;
|
||||
|
||||
constructor(config: LLMConfig) {
|
||||
this.google = new GoogleGenAI({ apiKey: config.apiKey });
|
||||
this.model = config.model || "gemini-2.0-flash";
|
||||
}
|
||||
|
||||
async generateResponse(
|
||||
messages: Message[],
|
||||
responseFormat?: { type: string },
|
||||
tools?: any[],
|
||||
): Promise<string | LLMResponse> {
|
||||
const completion = await this.google.models.generateContent({
|
||||
contents: messages.map((msg) => ({
|
||||
parts: [
|
||||
{
|
||||
text:
|
||||
typeof msg.content === "string"
|
||||
? msg.content
|
||||
: JSON.stringify(msg.content),
|
||||
},
|
||||
],
|
||||
role: msg.role === "system" ? "model" : "user",
|
||||
})),
|
||||
|
||||
model: this.model,
|
||||
// config: {
|
||||
// responseSchema: {}, // Add response schema if needed
|
||||
// },
|
||||
});
|
||||
|
||||
const text = completion.text?.replace(/^```json\n/, "").replace(/\n```$/, "");
|
||||
|
||||
return text || "";
|
||||
}
|
||||
|
||||
async generateChat(messages: Message[]): Promise<LLMResponse> {
|
||||
const completion = await this.google.models.generateContent({
|
||||
contents: messages,
|
||||
model: this.model,
|
||||
});
|
||||
const response = completion.candidates![0].content;
|
||||
return {
|
||||
content: response!.parts![0].text || "",
|
||||
role: response!.role!,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import { SQLiteManager } from "../storage/SQLiteManager";
|
||||
import { MemoryHistoryManager } from "../storage/MemoryHistoryManager";
|
||||
import { SupabaseHistoryManager } from "../storage/SupabaseHistoryManager";
|
||||
import { HistoryManager } from "../storage/base";
|
||||
import { GoogleEmbedder } from "../embeddings/google";
|
||||
import { GoogleLLM } from "../llms/google";
|
||||
|
||||
export class EmbedderFactory {
|
||||
static create(provider: string, config: EmbeddingConfig): Embedder {
|
||||
@@ -30,6 +32,8 @@ export class EmbedderFactory {
|
||||
return new OpenAIEmbedder(config);
|
||||
case "ollama":
|
||||
return new OllamaEmbedder(config);
|
||||
case "google":
|
||||
return new GoogleEmbedder(config);
|
||||
default:
|
||||
throw new Error(`Unsupported embedder provider: ${provider}`);
|
||||
}
|
||||
@@ -49,6 +53,8 @@ export class LLMFactory {
|
||||
return new GroqLLM(config);
|
||||
case "ollama":
|
||||
return new OllamaLLM(config);
|
||||
case "google":
|
||||
return new GoogleLLM(config);
|
||||
default:
|
||||
throw new Error(`Unsupported LLM provider: ${provider}`);
|
||||
}
|
||||
|
||||
+3
-2
@@ -130,13 +130,14 @@ class MemoryClient:
|
||||
"""
|
||||
kwargs = self._prepare_params(kwargs)
|
||||
if kwargs.get("output_format") != "v1.1":
|
||||
kwargs["output_format"] = "v1.1"
|
||||
warnings.warn(
|
||||
"Using default output format 'v1.0' is deprecated and will be removed in version 0.1.70. "
|
||||
"Please use output_format='v1.1' for enhanced memory details. "
|
||||
"output_format='v1.0' is deprecated therefore setting it to 'v1.1' by default."
|
||||
"Check out the docs for more information: https://docs.mem0.ai/platform/quickstart#4-1-create-memories",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
kwargs["version"] = "v2"
|
||||
payload = self._prepare_payload(messages, kwargs)
|
||||
response = self.client.post("/v1/memories/", json=payload)
|
||||
response.raise_for_status()
|
||||
|
||||
@@ -13,7 +13,7 @@ class BaseLlmConfig(ABC):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: Optional[str] = None,
|
||||
model: Optional[Union[str, Dict]] = None,
|
||||
temperature: float = 0.1,
|
||||
api_key: Optional[str] = None,
|
||||
max_tokens: int = 2000,
|
||||
|
||||
@@ -220,14 +220,14 @@ You are a memory summarization system that records and preserves the complete in
|
||||
Each numbered step must be a self-contained entry that includes all of the following elements:
|
||||
|
||||
1. **Agent Action**:
|
||||
- Precisely describe what the agent did (e.g., "Clicked on the 'Blog' link", "Called API to fetch content", "Scraped page data").
|
||||
- Precisely describe what the agent did (e.g., "Clicked on the 'Blog' link", "Called API to fetch content", "Scraped page data").
|
||||
- Include all parameters, target elements, or methods involved.
|
||||
|
||||
2. **Action Result (Mandatory, Unmodified)**:
|
||||
- Immediately follow the agent action with its exact, unaltered output.
|
||||
|
||||
2. **Action Result (Mandatory, Unmodified)**:
|
||||
- Immediately follow the agent action with its exact, unaltered output.
|
||||
- Record all returned data, responses, HTML snippets, JSON content, or error messages exactly as received. This is critical for constructing the final output later.
|
||||
|
||||
3. **Embedded Metadata**:
|
||||
|
||||
3. **Embedded Metadata**:
|
||||
For the same numbered step, include additional context such as:
|
||||
- **Key Findings**: Any important information discovered (e.g., URLs, data points, search results).
|
||||
- **Navigation History**: For browser agents, detail which pages were visited, including their URLs and relevance.
|
||||
@@ -246,6 +246,8 @@ You are a memory summarization system that records and preserves the complete in
|
||||
### Example Template:
|
||||
|
||||
```
|
||||
## Summary of the agent's execution history
|
||||
|
||||
**Task Objective**: Scrape blog post titles and full content from the OpenAI blog.
|
||||
**Progress Status**: 10% complete — 5 out of 50 blog posts processed.
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ class EmbedderConfig(BaseModel):
|
||||
"vertexai",
|
||||
"together",
|
||||
"lmstudio",
|
||||
"langchain",
|
||||
]:
|
||||
return v
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import os
|
||||
from typing import Literal, Optional
|
||||
|
||||
from mem0.configs.embeddings.base import BaseEmbedderConfig
|
||||
from mem0.embeddings.base import EmbeddingBase
|
||||
|
||||
try:
|
||||
from langchain.embeddings.base import Embeddings
|
||||
except ImportError:
|
||||
raise ImportError("langchain is not installed. Please install it using `pip install langchain`")
|
||||
|
||||
|
||||
class LangchainEmbedding(EmbeddingBase):
|
||||
def __init__(self, config: Optional[BaseEmbedderConfig] = None):
|
||||
super().__init__(config)
|
||||
|
||||
if self.config.model is None:
|
||||
raise ValueError("`model` parameter is required")
|
||||
|
||||
if not isinstance(self.config.model, Embeddings):
|
||||
raise ValueError("`model` must be an instance of Embeddings")
|
||||
|
||||
self.langchain_model = self.config.model
|
||||
|
||||
def embed(self, text, memory_action: Optional[Literal["add", "search", "update"]] = None):
|
||||
"""
|
||||
Get the embedding for the given text using Langchain.
|
||||
|
||||
Args:
|
||||
text (str): The text to embed.
|
||||
memory_action (optional): The type of embedding to use. Must be one of "add", "search", or "update". Defaults to None.
|
||||
Returns:
|
||||
list: The embedding vector.
|
||||
"""
|
||||
|
||||
return self.langchain_model.embed_query(text)
|
||||
@@ -25,6 +25,7 @@ class LlmConfig(BaseModel):
|
||||
"deepseek",
|
||||
"xai",
|
||||
"lmstudio",
|
||||
"langchain",
|
||||
):
|
||||
return v
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from mem0.configs.llms.base import BaseLlmConfig
|
||||
from mem0.llms.base import LLMBase
|
||||
|
||||
try:
|
||||
from langchain.chat_models.base import BaseChatModel
|
||||
except ImportError:
|
||||
raise ImportError("langchain is not installed. Please install it using `pip install langchain`")
|
||||
|
||||
|
||||
class LangchainLLM(LLMBase):
|
||||
def __init__(self, config: Optional[BaseLlmConfig] = None):
|
||||
super().__init__(config)
|
||||
|
||||
if self.config.model is None:
|
||||
raise ValueError("`model` parameter is required")
|
||||
|
||||
if not isinstance(self.config.model, BaseChatModel):
|
||||
raise ValueError("`model` must be an instance of BaseChatModel")
|
||||
|
||||
self.langchain_model = self.config.model
|
||||
|
||||
def generate_response(
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
response_format=None,
|
||||
tools: Optional[List[Dict]] = None,
|
||||
tool_choice: str = "auto",
|
||||
):
|
||||
"""
|
||||
Generate a response based on the given messages using langchain_community.
|
||||
|
||||
Args:
|
||||
messages (list): List of message dicts containing 'role' and 'content'.
|
||||
response_format (str or object, optional): Format of the response. Not used in Langchain.
|
||||
tools (list, optional): List of tools that the model can call. Not used in Langchain.
|
||||
tool_choice (str, optional): Tool choice method. Not used in Langchain.
|
||||
|
||||
Returns:
|
||||
str: The generated response.
|
||||
"""
|
||||
try:
|
||||
# Convert the messages to LangChain's tuple format
|
||||
langchain_messages = []
|
||||
for message in messages:
|
||||
role = message["role"]
|
||||
content = message["content"]
|
||||
|
||||
if role == "system":
|
||||
langchain_messages.append(("system", content))
|
||||
elif role == "user":
|
||||
langchain_messages.append(("human", content))
|
||||
elif role == "assistant":
|
||||
langchain_messages.append(("ai", content))
|
||||
|
||||
if not langchain_messages:
|
||||
raise ValueError("No valid messages found in the messages list")
|
||||
|
||||
ai_message = self.langchain_model.invoke(langchain_messages)
|
||||
|
||||
return ai_message.content
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"Error generating response using langchain model: {str(e)}")
|
||||
+11
-26
@@ -167,7 +167,9 @@ class MemoryGraph:
|
||||
for item in search_results["tool_calls"][0]["arguments"]["entities"]:
|
||||
entity_type_map[item["entity"]] = item["entity_type"]
|
||||
except Exception as e:
|
||||
logger.error(f"Error in search tool: {e}")
|
||||
logger.exception(
|
||||
f"Error in search tool: {e}, llm_provider={self.llm_provider}, search_results={search_results}"
|
||||
)
|
||||
|
||||
entity_type_map = {k.lower().replace(" ", "_"): v.lower().replace(" ", "_") for k, v in entity_type_map.items()}
|
||||
logger.debug(f"Entity type map: {entity_type_map}")
|
||||
@@ -203,14 +205,13 @@ class MemoryGraph:
|
||||
tools=_tools,
|
||||
)
|
||||
|
||||
entities = []
|
||||
if extracted_entities["tool_calls"]:
|
||||
extracted_entities = extracted_entities["tool_calls"][0]["arguments"]["entities"]
|
||||
else:
|
||||
extracted_entities = []
|
||||
entities = extracted_entities["tool_calls"][0]["arguments"]["entities"]
|
||||
|
||||
extracted_entities = self._remove_spaces_from_entities(extracted_entities)
|
||||
logger.debug(f"Extracted entities: {extracted_entities}")
|
||||
return extracted_entities
|
||||
entities = self._remove_spaces_from_entities(entities)
|
||||
logger.debug(f"Extracted entities: {entities}")
|
||||
return entities
|
||||
|
||||
def _search_graph_db(self, node_list, filters, limit=100):
|
||||
"""Search similar nodes among and their respective incoming and outgoing relations."""
|
||||
@@ -347,14 +348,9 @@ class MemoryGraph:
|
||||
params = {
|
||||
"source_id": source_node_search_result[0]["elementId(source_candidate)"],
|
||||
"destination_name": destination,
|
||||
"relationship": relationship,
|
||||
"destination_type": destination_type,
|
||||
"destination_embedding": dest_embedding,
|
||||
"user_id": user_id,
|
||||
}
|
||||
resp = self.graph.query(cypher, params=params)
|
||||
results.append(resp)
|
||||
|
||||
elif destination_node_search_result and not source_node_search_result:
|
||||
cypher = f"""
|
||||
MATCH (destination)
|
||||
@@ -372,14 +368,9 @@ class MemoryGraph:
|
||||
params = {
|
||||
"destination_id": destination_node_search_result[0]["elementId(destination_candidate)"],
|
||||
"source_name": source,
|
||||
"relationship": relationship,
|
||||
"source_type": source_type,
|
||||
"source_embedding": source_embedding,
|
||||
"user_id": user_id,
|
||||
}
|
||||
resp = self.graph.query(cypher, params=params)
|
||||
results.append(resp)
|
||||
|
||||
elif source_node_search_result and destination_node_search_result:
|
||||
cypher = f"""
|
||||
MATCH (source)
|
||||
@@ -396,12 +387,8 @@ class MemoryGraph:
|
||||
"source_id": source_node_search_result[0]["elementId(source_candidate)"],
|
||||
"destination_id": destination_node_search_result[0]["elementId(destination_candidate)"],
|
||||
"user_id": user_id,
|
||||
"relationship": relationship,
|
||||
}
|
||||
resp = self.graph.query(cypher, params=params)
|
||||
results.append(resp)
|
||||
|
||||
elif not source_node_search_result and not destination_node_search_result:
|
||||
else:
|
||||
cypher = f"""
|
||||
MERGE (n:{source_type} {{name: $source_name, user_id: $user_id}})
|
||||
ON CREATE SET n.created = timestamp(), n.embedding = $source_embedding
|
||||
@@ -415,15 +402,13 @@ class MemoryGraph:
|
||||
"""
|
||||
params = {
|
||||
"source_name": source,
|
||||
"source_type": source_type,
|
||||
"dest_name": destination,
|
||||
"destination_type": destination_type,
|
||||
"source_embedding": source_embedding,
|
||||
"dest_embedding": dest_embedding,
|
||||
"user_id": user_id,
|
||||
}
|
||||
resp = self.graph.query(cypher, params=params)
|
||||
results.append(resp)
|
||||
result = self.graph.query(cypher, params=params)
|
||||
results.append(result)
|
||||
return results
|
||||
|
||||
def _remove_spaces_from_entities(self, entity_list):
|
||||
|
||||
+15
-13
@@ -12,14 +12,12 @@ from pydantic import ValidationError
|
||||
|
||||
from mem0.configs.base import MemoryConfig, MemoryItem
|
||||
from mem0.configs.enums import MemoryType
|
||||
from mem0.configs.prompts import (PROCEDURAL_MEMORY_SYSTEM_PROMPT,
|
||||
get_update_memory_messages)
|
||||
from mem0.configs.prompts import PROCEDURAL_MEMORY_SYSTEM_PROMPT, get_update_memory_messages
|
||||
from mem0.memory.base import MemoryBase
|
||||
from mem0.memory.setup import setup_config
|
||||
from mem0.memory.storage import SQLiteManager
|
||||
from mem0.memory.telemetry import capture_event
|
||||
from mem0.memory.utils import (get_fact_retrieval_messages, parse_messages,
|
||||
parse_vision_messages, remove_code_blocks)
|
||||
from mem0.memory.utils import get_fact_retrieval_messages, parse_messages, parse_vision_messages, remove_code_blocks
|
||||
from mem0.utils.factory import EmbedderFactory, LlmFactory, VectorStoreFactory
|
||||
|
||||
# Setup user config
|
||||
@@ -89,6 +87,7 @@ class Memory(MemoryBase):
|
||||
infer=True,
|
||||
memory_type=None,
|
||||
prompt=None,
|
||||
llm=None,
|
||||
):
|
||||
"""
|
||||
Create a new memory.
|
||||
@@ -103,6 +102,7 @@ class Memory(MemoryBase):
|
||||
infer (bool, optional): Whether to infer the memories. Defaults to True.
|
||||
memory_type (str, optional): Type of memory to create. Defaults to None. By default, it creates the short term memories and long term (semantic and episodic) memories. Pass "procedural_memory" to create procedural memories.
|
||||
prompt (str, optional): Prompt to use for the memory creation. Defaults to None.
|
||||
llm (BaseChatModel, optional): LLM class to use for generating procedural memories. Defaults to None. Useful when user is using LangChain ChatModel.
|
||||
Returns:
|
||||
dict: A dictionary containing the result of the memory addition operation.
|
||||
result: dict of affected events with each dict has the following key:
|
||||
@@ -139,7 +139,7 @@ class Memory(MemoryBase):
|
||||
messages = [{"role": "user", "content": messages}]
|
||||
|
||||
if agent_id is not None and memory_type == MemoryType.PROCEDURAL.value:
|
||||
results = self._create_procedural_memory(messages, metadata, prompt)
|
||||
results = self._create_procedural_memory(messages, metadata=metadata, llm=llm, prompt=prompt)
|
||||
return results
|
||||
|
||||
if self.config.llm.config.get("enable_vision"):
|
||||
@@ -623,14 +623,21 @@ class Memory(MemoryBase):
|
||||
capture_event("mem0._create_memory", self, {"memory_id": memory_id})
|
||||
return memory_id
|
||||
|
||||
def _create_procedural_memory(self, messages, metadata, llm=None, prompt=None):
|
||||
def _create_procedural_memory(self, messages, metadata=None, prompt=None):
|
||||
"""
|
||||
Create a procedural memory
|
||||
|
||||
Args:
|
||||
messages (list): List of messages to create a procedural memory from.
|
||||
metadata (dict): Metadata to create a procedural memory from.
|
||||
prompt (str, optional): Prompt to use for the procedural memory creation. Defaults to None.
|
||||
"""
|
||||
try:
|
||||
from langchain_core.messages.utils import convert_to_messages # type: ignore
|
||||
except Exception:
|
||||
logger.error("Import error while loading langchain-core. Please install 'langchain-core' to use procedural memory.")
|
||||
logger.error(
|
||||
"Import error while loading langchain-core. Please install 'langchain-core' to use procedural memory."
|
||||
)
|
||||
raise
|
||||
|
||||
logger.info("Creating procedural memory")
|
||||
@@ -642,12 +649,7 @@ class Memory(MemoryBase):
|
||||
]
|
||||
|
||||
try:
|
||||
if llm is not None:
|
||||
parsed_messages = convert_to_messages(parsed_messages)
|
||||
response = llm.invoke(messages=parsed_messages)
|
||||
procedural_memory = response.content
|
||||
else:
|
||||
procedural_memory = self.llm.generate_response(messages=parsed_messages)
|
||||
procedural_memory = self.llm.generate_response(messages=parsed_messages)
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating procedural memory summary: {e}")
|
||||
raise
|
||||
|
||||
@@ -26,6 +26,7 @@ class LlmFactory:
|
||||
"deepseek": "mem0.llms.deepseek.DeepSeekLLM",
|
||||
"xai": "mem0.llms.xai.XAILLM",
|
||||
"lmstudio": "mem0.llms.lmstudio.LMStudioLLM",
|
||||
"langchain": "mem0.llms.langchain.LangchainLLM",
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@@ -49,6 +50,7 @@ class EmbedderFactory:
|
||||
"vertexai": "mem0.embeddings.vertexai.VertexAIEmbedding",
|
||||
"together": "mem0.embeddings.together.TogetherEmbedding",
|
||||
"lmstudio": "mem0.embeddings.lmstudio.LMStudioEmbedding",
|
||||
"langchain": "mem0.embeddings.langchain.LangchainEmbedding",
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -101,7 +101,6 @@ class FAISS(VectorStoreBase):
|
||||
faiss.write_index(self.index, index_path)
|
||||
with open(docstore_path, "wb") as f:
|
||||
pickle.dump((self.docstore, self.index_to_id), f)
|
||||
logger.info(f"Saved FAISS index to {index_path} with {self.index.ntotal} vectors")
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to save FAISS index: {e}")
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ class PGVector(VectorStoreBase):
|
||||
Args:
|
||||
embedding_model_dims (int): Dimension of the embedding vector.
|
||||
"""
|
||||
self.cur.execute("CREATE EXTENSION IF NOT EXISTS vector")
|
||||
self.cur.execute(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS {self.collection_name} (
|
||||
|
||||
Generated
+2
-64
@@ -48,56 +48,6 @@ files = [
|
||||
{file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azure-common"
|
||||
version = "1.1.28"
|
||||
description = "Microsoft Azure Client Library for Python (Common)"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "azure-common-1.1.28.zip", hash = "sha256:4ac0cd3214e36b6a1b6a442686722a5d8cc449603aa833f3f0f40bda836704a3"},
|
||||
{file = "azure_common-1.1.28-py2.py3-none-any.whl", hash = "sha256:5c12d3dcf4ec20599ca6b0d3e09e86e146353d443e7fcc050c9a19c1f9df20ad"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azure-core"
|
||||
version = "1.32.0"
|
||||
description = "Microsoft Azure Core Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "azure_core-1.32.0-py3-none-any.whl", hash = "sha256:eac191a0efb23bfa83fddf321b27b122b4ec847befa3091fa736a5c32c50d7b4"},
|
||||
{file = "azure_core-1.32.0.tar.gz", hash = "sha256:22b3c35d6b2dae14990f6c1be2912bf23ffe50b220e708a28ab1bb92b1c730e5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
requests = ">=2.21.0"
|
||||
six = ">=1.11.0"
|
||||
typing-extensions = ">=4.6.0"
|
||||
|
||||
[package.extras]
|
||||
aio = ["aiohttp (>=3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "azure-search-documents"
|
||||
version = "11.5.2"
|
||||
description = "Microsoft Azure Cognitive Search Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "azure_search_documents-11.5.2-py3-none-any.whl", hash = "sha256:c949d011008a4b0bcee3db91132741b4e4d50ddb3f7e2f48944d949d4b413b11"},
|
||||
{file = "azure_search_documents-11.5.2.tar.gz", hash = "sha256:98977dd1fa4978d3b7d8891a0856b3becb6f02cc07ff2e1ea40b9c7254ada315"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
azure-common = ">=1.1"
|
||||
azure-core = ">=1.28.0"
|
||||
isodate = ">=0.6.0"
|
||||
typing-extensions = ">=4.6.0"
|
||||
|
||||
[[package]]
|
||||
name = "backoff"
|
||||
version = "2.2.1"
|
||||
@@ -394,7 +344,7 @@ description = "Lightweight in-process concurrent programming"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.14\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"
|
||||
markers = "(platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\") and python_version < \"3.14\""
|
||||
files = [
|
||||
{file = "greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563"},
|
||||
{file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83"},
|
||||
@@ -732,18 +682,6 @@ files = [
|
||||
{file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isodate"
|
||||
version = "0.7.2"
|
||||
description = "An ISO 8601 date/time/duration parser and formatter"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15"},
|
||||
{file = "isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isort"
|
||||
version = "5.13.2"
|
||||
@@ -2303,4 +2241,4 @@ graph = ["langchain-neo4j", "neo4j", "rank-bm25"]
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.9,<4.0"
|
||||
content-hash = "f7bee9b294566e32c580fef1940cbc6fcb7fd6ca2e695f23c719d134af4c3204"
|
||||
content-hash = "5848e23bdd7b453f938c9b5f6171866faa01bdcc2651bedb83ee9f4fe90e8bc8"
|
||||
|
||||
+1
-2
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "mem0ai"
|
||||
version = "0.1.80"
|
||||
version = "0.1.84"
|
||||
description = "Long-term memory for AI Agents"
|
||||
authors = ["Mem0 <founders@mem0.ai>"]
|
||||
exclude = [
|
||||
@@ -30,7 +30,6 @@ sqlalchemy = "^2.0.31"
|
||||
langchain-neo4j = "^0.4.0"
|
||||
neo4j = "^5.23.1"
|
||||
rank-bm25 = "^0.2.2"
|
||||
azure-search-documents = "^11.5.0"
|
||||
psycopg2-binary = "^2.9.10"
|
||||
|
||||
[tool.poetry.extras]
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
OPENAI_API_KEY=
|
||||
NEO4J_URI=
|
||||
NEO4J_USERNAME=
|
||||
NEO4J_PASSWORD=
|
||||
|
||||
|
||||
POSTGRES_HOST=
|
||||
POSTGRES_PORT=
|
||||
POSTGRES_DB=
|
||||
POSTGRES_USER=
|
||||
POSTGRES_PASSWORD=
|
||||
POSTGRES_COLLECTION_NAME=
|
||||
@@ -0,0 +1,25 @@
|
||||
FROM python:3.12
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install Poetry
|
||||
RUN curl -sSL https://install.python-poetry.org | python3 -
|
||||
ENV PATH="/root/.local/bin:$PATH"
|
||||
|
||||
# Copy requirements first for better caching
|
||||
COPY server/requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
# Install mem0 in editable mode using Poetry
|
||||
WORKDIR /app/packages
|
||||
COPY pyproject.toml .
|
||||
COPY poetry.lock .
|
||||
COPY README.md .
|
||||
COPY mem0 ./mem0
|
||||
RUN pip install -e .[graph]
|
||||
|
||||
# Return to app directory and copy server code
|
||||
WORKDIR /app
|
||||
COPY server .
|
||||
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
||||
@@ -0,0 +1,74 @@
|
||||
name: mem0-dev
|
||||
|
||||
services:
|
||||
mem0:
|
||||
build:
|
||||
context: .. # Set context to parent directory
|
||||
dockerfile: server/dev.Dockerfile
|
||||
ports:
|
||||
- "8888:8000"
|
||||
env_file:
|
||||
- .env
|
||||
networks:
|
||||
- mem0_network
|
||||
volumes:
|
||||
- ./history:/app/history # History db location. By default, it creates a history.db file on the server folder
|
||||
- .:/app # Server code. This allows to reload the app when the server code is updated
|
||||
- ../mem0:/app/packages/mem0 # Mem0 library. This allows to reload the app when the library code is updated
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
neo4j:
|
||||
condition: service_healthy
|
||||
command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload # Enable auto-reload
|
||||
environment:
|
||||
- PYTHONDONTWRITEBYTECODE=1 # Prevents Python from writing .pyc files
|
||||
- PYTHONUNBUFFERED=1 # Ensures Python output is sent straight to terminal
|
||||
|
||||
postgres:
|
||||
image: ankane/pgvector:v0.5.1
|
||||
restart: on-failure
|
||||
shm_size: "128mb" # Increase this if vacuuming fails with a "no space left on device" error
|
||||
networks:
|
||||
- mem0_network
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-q", "-d", "postgres", "-U", "postgres"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
- postgres_db:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "8432:5432"
|
||||
neo4j:
|
||||
image: neo4j:5.26.4
|
||||
networks:
|
||||
- mem0_network
|
||||
healthcheck:
|
||||
test: wget http://localhost:7687 || exit 1
|
||||
interval: 1s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
start_period: 3s
|
||||
ports:
|
||||
- "8474:7474" # HTTP
|
||||
- "8687:7687" # Bolt
|
||||
volumes:
|
||||
- neo4j_data:/data
|
||||
environment:
|
||||
- NEO4J_AUTH=neo4j/mem0graph
|
||||
- NEO4J_PLUGINS=["apoc"] # Add this line to install APOC
|
||||
- NEO4J_apoc_export_file_enabled=true
|
||||
- NEO4J_apoc_import_file_enabled=true
|
||||
- NEO4J_apoc_import_file_use__neo4j__config=true
|
||||
|
||||
volumes:
|
||||
neo4j_data:
|
||||
postgres_db:
|
||||
|
||||
networks:
|
||||
mem0_network:
|
||||
driver: bridge
|
||||
+70
-1
@@ -6,10 +6,69 @@ from typing import Optional, List, Any, Dict
|
||||
from mem0 import Memory
|
||||
from dotenv import load_dotenv
|
||||
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
MEMORY_INSTANCE = Memory()
|
||||
|
||||
POSTGRES_HOST = os.environ.get("POSTGRES_HOST", "postgres")
|
||||
POSTGRES_PORT = os.environ.get("POSTGRES_PORT", "5432")
|
||||
POSTGRES_DB = os.environ.get("POSTGRES_DB", "postgres")
|
||||
POSTGRES_USER = os.environ.get("POSTGRES_USER", "postgres")
|
||||
POSTGRES_PASSWORD = os.environ.get("POSTGRES_PASSWORD", "postgres")
|
||||
POSTGRES_COLLECTION_NAME = os.environ.get("POSTGRES_COLLECTION_NAME", "memories")
|
||||
|
||||
NEO4J_URI = os.environ.get("NEO4J_URI", "bolt://neo4j:7687")
|
||||
NEO4J_USERNAME = os.environ.get("NEO4J_USERNAME", "neo4j")
|
||||
NEO4J_PASSWORD = os.environ.get("NEO4J_PASSWORD", "mem0graph")
|
||||
|
||||
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
|
||||
HISTORY_DB_PATH = os.environ.get("HISTORY_DB_PATH", "/app/history/history.db")
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
"version": "v1.1",
|
||||
"vector_store": {
|
||||
"provider": "pgvector",
|
||||
"config": {
|
||||
"host": POSTGRES_HOST,
|
||||
"port": int(POSTGRES_PORT),
|
||||
"dbname": POSTGRES_DB,
|
||||
"user": POSTGRES_USER,
|
||||
"password": POSTGRES_PASSWORD,
|
||||
"collection_name": POSTGRES_COLLECTION_NAME,
|
||||
}
|
||||
},
|
||||
"graph_store": {
|
||||
"provider": "neo4j",
|
||||
"config": {
|
||||
"url": NEO4J_URI,
|
||||
"username": NEO4J_USERNAME,
|
||||
"password": NEO4J_PASSWORD
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"api_key": OPENAI_API_KEY,
|
||||
"temperature": 0.2,
|
||||
"model": "gpt-4o"
|
||||
}
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"api_key": OPENAI_API_KEY,
|
||||
"model": "text-embedding-3-small"
|
||||
}
|
||||
},
|
||||
"history_db_path": HISTORY_DB_PATH,
|
||||
}
|
||||
|
||||
|
||||
MEMORY_INSTANCE = Memory.from_config(DEFAULT_CONFIG)
|
||||
|
||||
app = FastAPI(
|
||||
title="Mem0 REST APIs",
|
||||
@@ -36,6 +95,7 @@ class SearchRequest(BaseModel):
|
||||
user_id: Optional[str] = None
|
||||
run_id: Optional[str] = None
|
||||
agent_id: Optional[str] = None
|
||||
filters: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
@app.post("/configure", summary="Configure Mem0")
|
||||
@@ -59,6 +119,7 @@ def add_memory(memory_create: MemoryCreate):
|
||||
response = MEMORY_INSTANCE.add(messages=[m.model_dump() for m in memory_create.messages], **params)
|
||||
return JSONResponse(content=response)
|
||||
except Exception as e:
|
||||
logging.exception("Error in add_memory:") # This will log the full traceback
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@@ -75,6 +136,7 @@ def get_all_memories(
|
||||
params = {k: v for k, v in {"user_id": user_id, "run_id": run_id, "agent_id": agent_id}.items() if v is not None}
|
||||
return MEMORY_INSTANCE.get_all(**params)
|
||||
except Exception as e:
|
||||
logging.exception("Error in get_all_memories:")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@@ -84,6 +146,7 @@ def get_memory(memory_id: str):
|
||||
try:
|
||||
return MEMORY_INSTANCE.get(memory_id)
|
||||
except Exception as e:
|
||||
logging.exception("Error in get_memory:")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@@ -94,6 +157,7 @@ def search_memories(search_req: SearchRequest):
|
||||
params = {k: v for k, v in search_req.model_dump().items() if v is not None and k != "query"}
|
||||
return MEMORY_INSTANCE.search(query=search_req.query, **params)
|
||||
except Exception as e:
|
||||
logging.exception("Error in search_memories:")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@@ -103,6 +167,7 @@ def update_memory(memory_id: str, updated_memory: Dict[str, Any]):
|
||||
try:
|
||||
return MEMORY_INSTANCE.update(memory_id=memory_id, data=updated_memory)
|
||||
except Exception as e:
|
||||
logging.exception("Error in update_memory:")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@@ -112,6 +177,7 @@ def memory_history(memory_id: str):
|
||||
try:
|
||||
return MEMORY_INSTANCE.history(memory_id=memory_id)
|
||||
except Exception as e:
|
||||
logging.exception("Error in memory_history:")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@@ -122,6 +188,7 @@ def delete_memory(memory_id: str):
|
||||
MEMORY_INSTANCE.delete(memory_id=memory_id)
|
||||
return {"message": "Memory deleted successfully"}
|
||||
except Exception as e:
|
||||
logging.exception("Error in delete_memory:")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@@ -139,6 +206,7 @@ def delete_all_memories(
|
||||
MEMORY_INSTANCE.delete_all(**params)
|
||||
return {"message": "All relevant memories deleted"}
|
||||
except Exception as e:
|
||||
logging.exception("Error in delete_all_memories:")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@@ -149,6 +217,7 @@ def reset_memory():
|
||||
MEMORY_INSTANCE.reset()
|
||||
return {"message": "All memories reset"}
|
||||
except Exception as e:
|
||||
logging.exception("Error in reset_memory:")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@ from mem0.configs.embeddings.base import BaseEmbedderConfig
|
||||
|
||||
@pytest.fixture
|
||||
def mock_lm_studio_client():
|
||||
with patch("mem0.embeddings.lmstudio.Client") as mock_lm_studio:
|
||||
with patch("mem0.embeddings.lmstudio.OpenAI") as mock_openai:
|
||||
mock_client = Mock()
|
||||
mock_client.list.return_value = {"models": [{"name": "nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.f16.gguf"}]}
|
||||
mock_lm_studio.return_value = mock_client
|
||||
mock_client.embeddings.create.return_value = Mock(
|
||||
data=[Mock(embedding=[0.1, 0.2, 0.3, 0.4, 0.5])]
|
||||
)
|
||||
mock_openai.return_value = mock_client
|
||||
yield mock_client
|
||||
|
||||
|
||||
@@ -17,25 +19,11 @@ def test_embed_text(mock_lm_studio_client):
|
||||
config = BaseEmbedderConfig(model="nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.f16.gguf", embedding_dims=512)
|
||||
embedder = LMStudioEmbedding(config)
|
||||
|
||||
mock_response = {"embedding": [0.1, 0.2, 0.3, 0.4, 0.5]}
|
||||
mock_lm_studio_client.embeddings.return_value = mock_response
|
||||
|
||||
text = "Sample text to embed."
|
||||
embedding = embedder.embed(text)
|
||||
|
||||
mock_lm_studio_client.embeddings.assert_called_once_with(model="nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.f16.gguf", prompt=text)
|
||||
mock_lm_studio_client.embeddings.create.assert_called_once_with(
|
||||
input=["Sample text to embed."], model="nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.f16.gguf"
|
||||
)
|
||||
|
||||
assert embedding == [0.1, 0.2, 0.3, 0.4, 0.5]
|
||||
|
||||
|
||||
def test_ensure_model_exists(mock_lm_studio_client):
|
||||
config = BaseEmbedderConfig(model="nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.f16.gguf", embedding_dims=512)
|
||||
embedder = LMStudioEmbedding(config)
|
||||
|
||||
mock_lm_studio_client.pull.assert_not_called()
|
||||
|
||||
mock_lm_studio_client.list.return_value = {"models": []}
|
||||
|
||||
embedder._ensure_model_exists()
|
||||
|
||||
mock_lm_studio_client.pull.assert_called_once_with("nomic-embed-text")
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
from unittest.mock import Mock, patch
|
||||
import pytest
|
||||
|
||||
from mem0.configs.llms.base import BaseLlmConfig
|
||||
from mem0.llms.langchain import LangchainLLM
|
||||
|
||||
# Add the import for BaseChatModel
|
||||
try:
|
||||
from langchain.chat_models.base import BaseChatModel
|
||||
except ImportError:
|
||||
from unittest.mock import MagicMock
|
||||
BaseChatModel = MagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_langchain_model():
|
||||
"""Mock a Langchain model for testing."""
|
||||
mock_model = Mock(spec=BaseChatModel)
|
||||
mock_model.invoke.return_value = Mock(content="This is a test response")
|
||||
return mock_model
|
||||
|
||||
|
||||
def test_langchain_initialization(mock_langchain_model):
|
||||
"""Test that LangchainLLM initializes correctly with a valid model."""
|
||||
# Create a config with the model instance directly
|
||||
config = BaseLlmConfig(
|
||||
model=mock_langchain_model,
|
||||
temperature=0.7,
|
||||
max_tokens=100,
|
||||
api_key="test-api-key"
|
||||
)
|
||||
|
||||
# Initialize the LangchainLLM
|
||||
llm = LangchainLLM(config)
|
||||
|
||||
# Verify the model was correctly assigned
|
||||
assert llm.langchain_model == mock_langchain_model
|
||||
|
||||
|
||||
def test_generate_response(mock_langchain_model):
|
||||
"""Test that generate_response correctly processes messages and returns a response."""
|
||||
# Create a config with the model instance
|
||||
config = BaseLlmConfig(
|
||||
model=mock_langchain_model,
|
||||
temperature=0.7,
|
||||
max_tokens=100,
|
||||
api_key="test-api-key"
|
||||
)
|
||||
|
||||
# Initialize the LangchainLLM
|
||||
llm = LangchainLLM(config)
|
||||
|
||||
# Create test messages
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a helpful assistant."},
|
||||
{"role": "user", "content": "Hello, how are you?"},
|
||||
{"role": "assistant", "content": "I'm doing well! How can I help you?"},
|
||||
{"role": "user", "content": "Tell me a joke."}
|
||||
]
|
||||
|
||||
# Get response
|
||||
response = llm.generate_response(messages)
|
||||
|
||||
# Verify the correct message format was passed to the model
|
||||
expected_langchain_messages = [
|
||||
("system", "You are a helpful assistant."),
|
||||
("human", "Hello, how are you?"),
|
||||
("ai", "I'm doing well! How can I help you?"),
|
||||
("human", "Tell me a joke.")
|
||||
]
|
||||
|
||||
mock_langchain_model.invoke.assert_called_once()
|
||||
# Extract the first argument of the first call
|
||||
actual_messages = mock_langchain_model.invoke.call_args[0][0]
|
||||
assert actual_messages == expected_langchain_messages
|
||||
assert response == "This is a test response"
|
||||
|
||||
|
||||
def test_invalid_model():
|
||||
"""Test that LangchainLLM raises an error with an invalid model."""
|
||||
config = BaseLlmConfig(
|
||||
model="not-a-valid-model-instance",
|
||||
temperature=0.7,
|
||||
max_tokens=100,
|
||||
api_key="test-api-key"
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="`model` must be an instance of BaseChatModel"):
|
||||
LangchainLLM(config)
|
||||
|
||||
|
||||
def test_missing_model():
|
||||
"""Test that LangchainLLM raises an error when model is None."""
|
||||
config = BaseLlmConfig(
|
||||
model=None,
|
||||
temperature=0.7,
|
||||
max_tokens=100,
|
||||
api_key="test-api-key"
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="`model` parameter is required"):
|
||||
LangchainLLM(config)
|
||||
@@ -8,27 +8,39 @@ from mem0.llms.lmstudio import LMStudioLLM
|
||||
|
||||
@pytest.fixture
|
||||
def mock_lm_studio_client():
|
||||
with patch("mem0.llms.lmstudio.Client") as mock_lm_studio:
|
||||
with patch("mem0.llms.lmstudio.OpenAI") as mock_openai: # Corrected path
|
||||
mock_client = Mock()
|
||||
mock_client.list.return_value = {"models": [{"name": "lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGUF/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf"}]}
|
||||
mock_lm_studio.return_value = mock_client
|
||||
mock_client.chat.completions.create.return_value = Mock(
|
||||
choices=[
|
||||
Mock(message=Mock(content="I'm doing well, thank you for asking!"))
|
||||
]
|
||||
)
|
||||
mock_openai.return_value = mock_client
|
||||
yield mock_client
|
||||
|
||||
|
||||
def test_generate_response_without_tools(mock_lm_studio_client):
|
||||
config = BaseLlmConfig(model="lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGUF/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf", temperature=0.7, max_tokens=100, top_p=1.0)
|
||||
config = BaseLlmConfig(
|
||||
model="lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGUF/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf",
|
||||
temperature=0.7,
|
||||
max_tokens=100,
|
||||
top_p=1.0,
|
||||
)
|
||||
llm = LMStudioLLM(config)
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a helpful assistant."},
|
||||
{"role": "user", "content": "Hello, how are you?"},
|
||||
]
|
||||
|
||||
mock_response = {"message": {"content": "I'm doing well, thank you for asking!"}}
|
||||
mock_lm_studio_client.chat.return_value = mock_response
|
||||
|
||||
response = llm.generate_response(messages)
|
||||
|
||||
mock_lm_studio_client.chat.assert_called_once_with(
|
||||
model="lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGUF/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf", messages=messages, options={"temperature": 0.7, "num_predict": 100, "top_p": 1.0}
|
||||
mock_lm_studio_client.chat.completions.create.assert_called_once_with(
|
||||
model="lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGUF/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf",
|
||||
messages=messages,
|
||||
temperature=0.7,
|
||||
max_tokens=100,
|
||||
top_p=1.0,
|
||||
response_format={"type": "json_object"},
|
||||
)
|
||||
|
||||
assert response == "I'm doing well, thank you for asking!"
|
||||
|
||||
@@ -38,7 +38,7 @@ def mock_clients():
|
||||
# Stub required methods on index_client.
|
||||
mock_index_client.create_or_update_index = Mock()
|
||||
mock_index_client.list_indexes = Mock()
|
||||
mock_index_client.list_index_names = Mock(return_value=["test-index"])
|
||||
mock_index_client.list_index_names = Mock(return_value=[])
|
||||
mock_index_client.delete_index = Mock()
|
||||
# For col_info() we assume get_index returns an object with name and fields attributes.
|
||||
fake_index = Mock()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mem0/vercel-ai-provider",
|
||||
"version": "0.0.14",
|
||||
"version": "1.0.0",
|
||||
"description": "Vercel AI Provider for providing memory to LLMs",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
@@ -34,7 +34,7 @@
|
||||
"@ai-sdk/provider-utils": "2.1.10",
|
||||
"ai": "4.1.46",
|
||||
"dotenv": "^16.4.5",
|
||||
"mem0ai": "^1.0.29",
|
||||
"mem0ai": "^2.1.12",
|
||||
"partial-json": "0.1.7",
|
||||
"zod": "^3.0.0"
|
||||
},
|
||||
@@ -66,5 +66,12 @@
|
||||
"directories": {
|
||||
"example": "example",
|
||||
"test": "tests"
|
||||
},
|
||||
"packageManager": "pnpm@10.5.2+sha512.da9dc28cd3ff40d0592188235ab25d3202add8a207afbedc682220e4a0029ffbff4562102b9e6e46b4e3f9e8bd53e6d05de48544b0c57d4b0179e22c76d1199b",
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild",
|
||||
"sqlite3"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+5697
File diff suppressed because it is too large
Load Diff
@@ -31,9 +31,14 @@ export class Mem0GenericLanguageModel implements LanguageModelV1 {
|
||||
provider: string;
|
||||
|
||||
private async processMemories(messagesPrompts: LanguageModelV1Message[], mem0Config: Mem0ConfigSettings) {
|
||||
const memories = await getMemories(messagesPrompts, mem0Config);
|
||||
// Add New Memories
|
||||
await addMemories(messagesPrompts, mem0Config);
|
||||
addMemories(messagesPrompts, mem0Config).then((res) => {
|
||||
return res;
|
||||
});
|
||||
|
||||
// Get Memories
|
||||
const memories = await getMemories(messagesPrompts, mem0Config);
|
||||
|
||||
const mySystemPrompt = "These are the memories I have stored. Give more weightage to the question by users and try to answer that first. You have to modify your answer based on the memories I have provided. If the memories are irrelevant you can ignore them. Also don't reply to this section of the prompt, or the memories, they are only for your reference. The System prompt starts after text System Message: \n\n";
|
||||
|
||||
let memoriesText = "";
|
||||
|
||||
@@ -26,6 +26,8 @@ export interface Mem0ConfigSettings {
|
||||
page_size?: number;
|
||||
mem0ApiKey?: string;
|
||||
top_k?: number;
|
||||
threshold?: number;
|
||||
rerank?: boolean;
|
||||
}
|
||||
|
||||
export interface Mem0ChatConfig extends Mem0ConfigSettings, Mem0ProviderSettings {}
|
||||
|
||||
@@ -71,7 +71,7 @@ const searchInternalMemories = async (query: string, config?: Mem0ConfigSettings
|
||||
environmentVariableName: "MEM0_API_KEY",
|
||||
description: "Mem0",
|
||||
})}`, 'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({query, filters, top_k: config&&config.top_k || top_k, version: "v2", ...org_project_filters}),
|
||||
body: JSON.stringify({query, filters, ...config, top_k: config&&config.top_k || top_k, version: "v2", ...org_project_filters}),
|
||||
};
|
||||
const response = await fetch('https://api.mem0.ai/v2/memories/search/', options);
|
||||
const data = await response.json();
|
||||
|
||||
Reference in New Issue
Block a user