Updated Docs to add Mem0 Demo Link/ Updated Mem0 Demo (#2305)
This commit is contained in:
12
README.md
12
README.md
@@ -16,6 +16,8 @@
|
||||
<a href="https://mem0.ai">Learn more</a>
|
||||
·
|
||||
<a href="https://mem0.dev/DiG">Join Discord</a>
|
||||
·
|
||||
<a href="https://mem0.dev/demo">Demo</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
@@ -129,15 +131,17 @@ For more advanced usage and API documentation, visit our [documentation](https:/
|
||||
|
||||
## Demos
|
||||
|
||||
- AI Companion: Experience personalized conversations with an AI that remembers your preferences and past interactions
|
||||
- Mem0 - ChatGPT with Memory: A personalized AI chat app powered by Mem0 that remembers your preferences, facts, and memories.
|
||||
|
||||
[AI Companion Demo](https://github.com/user-attachments/assets/3fc72023-a72c-4593-8be0-3cee3ba744da)
|
||||
[Mem0 - ChatGPT with Memory](https://github.com/user-attachments/assets/cebc4f8e-bdb9-4837-868d-13c5ab7bb433)
|
||||
|
||||
Try live [demo](https://mem0.dev/demo/)
|
||||
|
||||
<br/><br/>
|
||||
|
||||
- Mem0 Demo: A personalized AI chat app powered by Mem0 that remembers your preferences, facts, and memories.
|
||||
- AI Companion: Experience personalized conversations with an AI that remembers your preferences and past interactions
|
||||
|
||||
[Mem0 Demo](https://github.com/user-attachments/assets/cebc4f8e-bdb9-4837-868d-13c5ab7bb433)
|
||||
[AI Companion Demo](https://github.com/user-attachments/assets/3fc72023-a72c-4593-8be0-3cee3ba744da)
|
||||
|
||||
<br/><br/>
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
},
|
||||
{
|
||||
"anchor": "Demo",
|
||||
"href": "https://demo.mem0.ai",
|
||||
"href": "https://mem0.dev/demo",
|
||||
"icon": "play"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -13,6 +13,8 @@ You can create a personalized AI Companion using Mem0. This guide will walk you
|
||||
src="https://github.com/user-attachments/assets/cebc4f8e-bdb9-4837-868d-13c5ab7bb433"
|
||||
></video>
|
||||
|
||||
You can try the [Mem0 Demo](https://mem0.dev/demo) live here.
|
||||
|
||||
## Overview
|
||||
|
||||
The Personalized AI Companion leverages Mem0 to retain information across interactions, enabling a tailored learning experience. It creates memories for each user interaction and integrates with OpenAI's GPT models to provide detailed and context-aware responses to user queries.
|
||||
|
||||
@@ -52,10 +52,6 @@ Currently, we support Neo4j as a graph store provider. You can setup [Neo4j](htt
|
||||
|
||||
<Note>If you are using Neo4j locally, then you need to install [APOC plugins](https://neo4j.com/labs/apoc/4.1/installation/).</Note>
|
||||
|
||||
<Note>
|
||||
If you are using NodeSDK, you need to pass `enableGraph` as `true` in the `config` object.
|
||||
</Note>
|
||||
|
||||
User can also customize the LLM for Graph Memory from the [Supported LLM list](https://docs.mem0.ai/components/llms/overview) with three levels of configuration:
|
||||
|
||||
1. **Main Configuration**: If `llm` is set in the main config, it will be used for all graph operations.
|
||||
@@ -163,6 +159,10 @@ const memory = new Memory(config);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
If you are using NodeSDK, you need to pass `enableGraph` as `true` in the `config` object.
|
||||
</Note>
|
||||
|
||||
## Graph Operations
|
||||
The Mem0's graph supports the following operations:
|
||||
|
||||
|
||||
@@ -74,14 +74,14 @@ const messages = [
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
||||
]
|
||||
|
||||
await memory.add(messages, { userId: "user123", metadata: { category: "movie_recommendations" } });
|
||||
await memory.add(messages, { userId: "alice", metadata: { category: "movie_recommendations" } });
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "c03c9045-df76-4949-bbc5-d5dc1932aa5c",
|
||||
"id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"memory": "User is planning to watch a movie tonight.",
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
@@ -111,7 +111,7 @@ await memory.add(messages, { userId: "user123", metadata: { category: "movie_rec
|
||||
<CodeGroup>
|
||||
```typescript Code
|
||||
// Get all memories
|
||||
const allMemories = await memory.getAll({ userId: "user123" });
|
||||
const allMemories = await memory.getAll({ userId: "alice" });
|
||||
console.log(allMemories)
|
||||
```
|
||||
|
||||
@@ -127,7 +127,7 @@ console.log(allMemories)
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
"userId": "alice"
|
||||
},
|
||||
{
|
||||
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
|
||||
@@ -138,7 +138,7 @@ console.log(allMemories)
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
"userId": "alice"
|
||||
},
|
||||
{
|
||||
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
|
||||
@@ -149,7 +149,7 @@ console.log(allMemories)
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
"userId": "alice"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -176,7 +176,7 @@ console.log(singleMemory);
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
"userId": "alice"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -185,7 +185,7 @@ console.log(singleMemory);
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Code
|
||||
const result = await memory.search('What do you know about me?', { userId: "user123" });
|
||||
const result = await memory.search('What do you know about me?', { userId: "alice" });
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
@@ -202,7 +202,7 @@ console.log(result);
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
"userId": "alice"
|
||||
},
|
||||
{
|
||||
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
|
||||
@@ -214,7 +214,7 @@ console.log(result);
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
"userId": "alice"
|
||||
},
|
||||
{
|
||||
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
|
||||
@@ -226,7 +226,7 @@ console.log(result);
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
"userId": "alice"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -263,23 +263,23 @@ console.log(history);
|
||||
[
|
||||
{
|
||||
"id": 39,
|
||||
"memory_id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"previous_value": "User is planning to watch a movie tonight.",
|
||||
"new_value": "I love India, it is my favorite country.",
|
||||
"memoryId": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"previousValue": "User is planning to watch a movie tonight.",
|
||||
"newValue": "I love India, it is my favorite country.",
|
||||
"action": "UPDATE",
|
||||
"created_at": "2025-02-27T16:33:20.557Z",
|
||||
"updated_at": "2025-02-27T16:33:27.051Z",
|
||||
"is_deleted": 0
|
||||
"createdAt": "2025-02-27T16:33:20.557Z",
|
||||
"updatedAt": "2025-02-27T16:33:27.051Z",
|
||||
"isDeleted": 0
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"memory_id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"previous_value": null,
|
||||
"new_value": "User is planning to watch a movie tonight.",
|
||||
"memoryId": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"previousValue": null,
|
||||
"newValue": "User is planning to watch a movie tonight.",
|
||||
"action": "ADD",
|
||||
"created_at": "2025-02-27T16:33:20.557Z",
|
||||
"updated_at": null,
|
||||
"is_deleted": 0
|
||||
"createdAt": "2025-02-27T16:33:20.557Z",
|
||||
"updatedAt": null,
|
||||
"isDeleted": 0
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -292,7 +292,7 @@ console.log(history);
|
||||
await memory.delete('892db2ae-06d9-49e5-8b3e-585ef9b85b8e');
|
||||
|
||||
// Delete all memories for a user
|
||||
await memory.deleteAll({ userId: "user123" });
|
||||
await memory.deleteAll({ userId: "alice" });
|
||||
```
|
||||
|
||||
### Reset Memory
|
||||
@@ -327,6 +327,15 @@ Mem0 offers extensive configuration options to customize its behavior according
|
||||
| `openaiBaseUrl` | Base URL for OpenAI API | OpenAI |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Graph Store Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|-------------|
|
||||
| `provider` | Graph store provider (e.g., "neo4j") | "neo4j" |
|
||||
| `url` | Connection URL | env.NEO4J_URL |
|
||||
| `username` | Authentication username | env.NEO4J_USERNAME |
|
||||
| `password` | Authentication password | env.NEO4J_PASSWORD |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Embedder Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|------------------------------|
|
||||
|
||||
@@ -85,20 +85,43 @@ m = Memory.from_config(config_dict=config)
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# For a user
|
||||
result = m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
const 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."}
|
||||
]
|
||||
|
||||
# messages = [
|
||||
# {"role": "user", "content": "Hi, I'm Alex. I like to play cricket on weekends."},
|
||||
# {"role": "assistant", "content": "Hello Alex! It's great to know that you enjoy playing cricket on weekends. I'll remember that for future reference."}
|
||||
# ]
|
||||
# client.add(messages, user_id="alice")
|
||||
result = m.add(messages, user_id="alice", metadata={"category": "movie_recommendations"})
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b", "memory": "Likes to play cricket on weekends", "event": "ADD"}
|
||||
{
|
||||
"id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"memory": "User is planning to watch a movie tonight.",
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
|
||||
"memory": "User is not a big fan of thriller movies.",
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
|
||||
"memory": "User loves sci-fi movies.",
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -115,14 +138,38 @@ all_memories = m.get_all(user_id="alice")
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"memory": "User is planning to watch a movie tonight.",
|
||||
"hash": "1a271c007316c94377175ee80e746a19",
|
||||
"created_at": "2025-02-27T16:33:20.557Z",
|
||||
"updated_at": "2025-02-27T16:33:27.051Z",
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"user_id": "alice"
|
||||
},
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
|
||||
"memory": "User loves sci-fi movies.",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"created_at": "2025-02-27T16:33:20.560Z",
|
||||
"updated_at": None,
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"user_id": "alice"
|
||||
},
|
||||
{
|
||||
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
|
||||
"memory": "User is not a big fan of thriller movies.",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"created_at": "2025-02-27T16:33:20.560Z",
|
||||
"updated_at": None,
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"user_id": "alice"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -135,18 +182,20 @@ all_memories = m.get_all(user_id="alice")
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# Get a single memory by ID
|
||||
specific_memory = m.get("bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
specific_memory = m.get("892db2ae-06d9-49e5-8b3e-585ef9b85b8e")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
"id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"memory": "User is planning to watch a movie tonight.",
|
||||
"hash": "1a271c007316c94377175ee80e746a19",
|
||||
"created_at": "2025-02-27T16:33:20.557Z",
|
||||
"updated_at": None,
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"user_id": "alice"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -155,23 +204,49 @@ specific_memory = m.get("bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")
|
||||
related_memories = m.search(query="What do you know about me?", user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"score": 0.30808347,
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
}
|
||||
]
|
||||
"results": [
|
||||
{
|
||||
"id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"memory": "User is planning to watch a movie tonight.",
|
||||
"hash": "1a271c007316c94377175ee80e746a19",
|
||||
"created_at": "2025-02-27T16:33:20.557Z",
|
||||
"updated_at": None,
|
||||
"score": 0.38920719231944799,
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"user_id": "alice"
|
||||
},
|
||||
{
|
||||
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
|
||||
"memory": "User loves sci-fi movies.",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"created_at": "2025-02-27T16:33:20.560Z",
|
||||
"updated_at": None,
|
||||
"score": 0.36869761478135689,
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"user_id": "alice"
|
||||
},
|
||||
{
|
||||
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
|
||||
"memory": "User is not a big fan of thriller movies.",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"created_at": "2025-02-27T16:33:20.560Z",
|
||||
"updated_at": None,
|
||||
"score": 0.33855272141248272,
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"user_id": "alice"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -180,7 +255,7 @@ related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
result = m.update(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b", data="Likes to play tennis on weekends")
|
||||
result = m.update(memory_id="892db2ae-06d9-49e5-8b3e-585ef9b85b8e", data="I love India, it is my favorite country.")
|
||||
```
|
||||
|
||||
```json Output
|
||||
@@ -192,29 +267,31 @@ result = m.update(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b", data="Likes
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
history = m.history(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
history = m.history(memory_id="892db2ae-06d9-49e5-8b3e-585ef9b85b8e")
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "96d2821d-e551-4089-aa57-9398c421d450",
|
||||
"memory_id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"old_memory": None,
|
||||
"new_memory": "Likes to play cricket on weekends",
|
||||
"event": "ADD",
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None
|
||||
},
|
||||
{
|
||||
"id": "3db4cb58-c0f1-4dd0-b62a-8123068ebfe7",
|
||||
"memory_id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"old_memory": "Likes to play cricket on weekends",
|
||||
"new_memory": "Likes to play tennis on weekends",
|
||||
"event": "UPDATE",
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": "2024-10-28T13:05:46.987978-07:00"
|
||||
}
|
||||
{
|
||||
"id": 39,
|
||||
"memory_id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"previous_value": "User is planning to watch a movie tonight.",
|
||||
"new_value": "I love India, it is my favorite country.",
|
||||
"action": "UPDATE",
|
||||
"created_at": "2025-02-27T16:33:20.557Z",
|
||||
"updated_at": "2025-02-27T16:33:27.051Z",
|
||||
"is_deleted": 0
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"memory_id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"previous_value": null,
|
||||
"new_value": "User is planning to watch a movie tonight.",
|
||||
"action": "ADD",
|
||||
"created_at": "2025-02-27T16:33:20.557Z",
|
||||
"updated_at": null,
|
||||
"is_deleted": 0
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -223,7 +300,7 @@ history = m.history(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
|
||||
```python
|
||||
# Delete a memory by id
|
||||
m.delete(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
m.delete(memory_id="892db2ae-06d9-49e5-8b3e-585ef9b85b8e")
|
||||
# Delete all memories for a user
|
||||
m.delete_all(user_id="alice")
|
||||
```
|
||||
|
||||
@@ -92,8 +92,8 @@ export const Assistant = () => {
|
||||
</header>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-[260px_1fr] gap-x-0 h-[calc(100vh-8rem)] md:h-[calc(100vh-4rem)]">
|
||||
<ThreadList onResetUserId={resetUserId} />
|
||||
<Thread sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} onResetUserId={resetUserId} />
|
||||
<ThreadList onResetUserId={resetUserId} isDarkMode={isDarkMode} />
|
||||
<Thread sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} onResetUserId={resetUserId} isDarkMode={isDarkMode} />
|
||||
</div>
|
||||
</div>
|
||||
</AssistantRuntimeProvider>
|
||||
|
||||
@@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Mem0-Demo",
|
||||
description: "Mem0-Demo: By Mem0",
|
||||
title: "Mem0 - ChatGPT with Memory",
|
||||
description: "Mem0 - ChatGPT with Memory is a personalized AI chat app powered by Mem0 that remembers your preferences, facts, and memories.",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
@@ -19,55 +19,73 @@ import {
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
|
||||
import ThemeAwareLogo from "@/components/assistant-ui/theme-aware-logo";
|
||||
import Link from "next/link";
|
||||
interface ThreadListProps {
|
||||
onResetUserId?: () => void;
|
||||
isDarkMode: boolean;
|
||||
}
|
||||
|
||||
export const ThreadList: FC<ThreadListProps> = ({ onResetUserId }) => {
|
||||
export const ThreadList: FC<ThreadListProps> = ({ onResetUserId, isDarkMode }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="flex-col h-full border-r border-[#e2e8f0] bg-white dark:bg-zinc-900 dark:border-zinc-800 p-3 overflow-y-auto hidden md:flex">
|
||||
<ThreadListPrimitive.Root className="flex flex-col items-stretch gap-1.5">
|
||||
<ThreadListNew />
|
||||
<div className="mt-4 mb-2 flex justify-between items-center px-2.5">
|
||||
<h2 className="text-sm font-medium text-[#475569] dark:text-zinc-300">Recent Chats</h2>
|
||||
{onResetUserId && (
|
||||
<AlertDialog open={open} onOpenChange={setOpen}>
|
||||
<AlertDialogTrigger asChild>
|
||||
<TooltipIconButton
|
||||
tooltip="Reset Memory"
|
||||
className="hover:text-[#4f46e5] text-[#475569] dark:text-zinc-300 dark:hover:text-[#6366f1] size-4 p-0"
|
||||
variant="ghost"
|
||||
>
|
||||
<RefreshCwIcon className="w-4 h-4" />
|
||||
</TooltipIconButton>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent className="bg-white dark:bg-zinc-900 border-[#e2e8f0] dark:border-zinc-800">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle className="text-[#1e293b] dark:text-white">Reset Memory</AlertDialogTitle>
|
||||
<AlertDialogDescription className="text-[#475569] dark:text-zinc-300">
|
||||
This will permanently delete all your chat history and memories. This action cannot be undone.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel className="text-[#475569] dark:text-zinc-300 hover:bg-[#eef2ff] dark:hover:bg-zinc-800">Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={() => {
|
||||
onResetUserId();
|
||||
setOpen(false);
|
||||
}}
|
||||
className="bg-[#4f46e5] hover:bg-[#4338ca] dark:bg-[#6366f1] dark:hover:bg-[#4f46e5] text-white"
|
||||
<ThreadListPrimitive.Root className="flex flex-col justify-between h-full items-stretch gap-1.5">
|
||||
<div className="flex flex-col h-full items-stretch gap-1.5">
|
||||
<ThreadListNew />
|
||||
<div className="mt-4 mb-2 flex justify-between items-center px-2.5">
|
||||
<h2 className="text-sm font-medium text-[#475569] dark:text-zinc-300">
|
||||
Recent Chats
|
||||
</h2>
|
||||
{onResetUserId && (
|
||||
<AlertDialog open={open} onOpenChange={setOpen}>
|
||||
<AlertDialogTrigger asChild>
|
||||
<TooltipIconButton
|
||||
tooltip="Reset Memory"
|
||||
className="hover:text-[#4f46e5] text-[#475569] dark:text-zinc-300 dark:hover:text-[#6366f1] size-4 p-0"
|
||||
variant="ghost"
|
||||
>
|
||||
Reset
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
)}
|
||||
<RefreshCwIcon className="w-4 h-4" />
|
||||
</TooltipIconButton>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent className="bg-white dark:bg-zinc-900 border-[#e2e8f0] dark:border-zinc-800">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle className="text-[#1e293b] dark:text-white">
|
||||
Reset Memory
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription className="text-[#475569] dark:text-zinc-300">
|
||||
This will permanently delete all your chat history and
|
||||
memories. This action cannot be undone.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel className="text-[#475569] dark:text-zinc-300 hover:bg-[#eef2ff] dark:hover:bg-zinc-800">
|
||||
Cancel
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={() => {
|
||||
onResetUserId();
|
||||
setOpen(false);
|
||||
}}
|
||||
className="bg-[#4f46e5] hover:bg-[#4338ca] dark:bg-[#6366f1] dark:hover:bg-[#4f46e5] text-white"
|
||||
>
|
||||
Reset
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
)}
|
||||
</div>
|
||||
<ThreadListItems />
|
||||
</div>
|
||||
<div>
|
||||
<Link href="https://www.assistant-ui.com/" target="_blank" className="flex justify-center items-center gap-2">
|
||||
<h1 className="text-sm text-[#475569] dark:text-zinc-300 text-center">built using</h1>
|
||||
<ThemeAwareLogo width={24} height={24} isDarkMode={isDarkMode} />
|
||||
<p className="text-md font-bold dark:text-zinc-300">assistant-ui</p>
|
||||
</Link>
|
||||
</div>
|
||||
<ThreadListItems />
|
||||
</ThreadListPrimitive.Root>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ActionBarPrimitive,
|
||||
@@ -42,14 +42,22 @@ import {
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import Link from "next/link";
|
||||
import ThemeAwareLogo from "./theme-aware-logo";
|
||||
|
||||
interface ThreadProps {
|
||||
sidebarOpen: boolean;
|
||||
setSidebarOpen: Dispatch<SetStateAction<boolean>>;
|
||||
onResetUserId?: () => void;
|
||||
isDarkMode: boolean;
|
||||
}
|
||||
|
||||
export const Thread: FC<ThreadProps> = ({ sidebarOpen, setSidebarOpen, onResetUserId }) => {
|
||||
export const Thread: FC<ThreadProps> = ({
|
||||
sidebarOpen,
|
||||
setSidebarOpen,
|
||||
onResetUserId,
|
||||
isDarkMode,
|
||||
}) => {
|
||||
const [resetDialogOpen, setResetDialogOpen] = useState(false);
|
||||
|
||||
return (
|
||||
@@ -68,16 +76,21 @@ export const Thread: FC<ThreadProps> = ({ sidebarOpen, setSidebarOpen, onResetUs
|
||||
)}
|
||||
|
||||
{/* Mobile sidebar drawer */}
|
||||
<div className={cn(
|
||||
"fixed inset-y-0 left-0 z-40 w-[85%] bg-white dark:bg-zinc-900 transform transition-transform duration-300 ease-in-out md:hidden",
|
||||
sidebarOpen ? "translate-x-0" : "-translate-x-full"
|
||||
)}>
|
||||
<div
|
||||
className={cn(
|
||||
"fixed inset-y-0 left-0 z-40 w-[85%] bg-white dark:bg-zinc-900 transform transition-transform duration-300 ease-in-out md:hidden",
|
||||
sidebarOpen ? "translate-x-0" : "-translate-x-full"
|
||||
)}
|
||||
>
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="flex items-center justify-between border-b dark:text-white border-[#e2e8f0] dark:border-zinc-800 p-4">
|
||||
<h2 className="font-medium">Recent Chats</h2>
|
||||
<div className="flex items-center gap-2">
|
||||
{onResetUserId && (
|
||||
<AlertDialog open={resetDialogOpen} onOpenChange={setResetDialogOpen}>
|
||||
<AlertDialog
|
||||
open={resetDialogOpen}
|
||||
onOpenChange={setResetDialogOpen}
|
||||
>
|
||||
<AlertDialogTrigger asChild>
|
||||
<TooltipIconButton
|
||||
tooltip="Reset Memory"
|
||||
@@ -89,13 +102,18 @@ export const Thread: FC<ThreadProps> = ({ sidebarOpen, setSidebarOpen, onResetUs
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent className="bg-white dark:bg-zinc-900 border-[#e2e8f0] dark:border-zinc-800">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle className="text-[#1e293b] dark:text-white">Reset Memory</AlertDialogTitle>
|
||||
<AlertDialogTitle className="text-[#1e293b] dark:text-white">
|
||||
Reset Memory
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription className="text-[#475569] dark:text-zinc-300">
|
||||
This will permanently delete all your chat history and memories. This action cannot be undone.
|
||||
This will permanently delete all your chat history and
|
||||
memories. This action cannot be undone.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel className="text-[#475569] dark:text-zinc-300 hover:bg-[#eef2ff] dark:hover:bg-zinc-800">Cancel</AlertDialogCancel>
|
||||
<AlertDialogCancel className="text-[#475569] dark:text-zinc-300 hover:bg-[#eef2ff] dark:hover:bg-zinc-800">
|
||||
Cancel
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={() => {
|
||||
onResetUserId();
|
||||
@@ -120,21 +138,40 @@ export const Thread: FC<ThreadProps> = ({ sidebarOpen, setSidebarOpen, onResetUs
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto p-3">
|
||||
<ThreadListPrimitive.Root className="flex flex-col items-stretch gap-1.5 h-full dark:text-white">
|
||||
<ThreadListPrimitive.New asChild>
|
||||
<Button
|
||||
className="hover:bg-[#eef2ff] dark:hover:bg-zinc-800 dark:data-[active]:bg-zinc-800 flex items-center justify-start gap-1 rounded-lg px-2.5 py-2 text-start bg-[#4f46e5] text-white dark:bg-[#6366f1]"
|
||||
variant="default"
|
||||
<div className="flex flex-col justify-between items-stretch gap-1.5 h-full dark:text-white">
|
||||
<ThreadListPrimitive.Root className="flex flex-col items-stretch gap-1.5 h-full dark:text-white">
|
||||
<ThreadListPrimitive.New asChild>
|
||||
<Button
|
||||
className="hover:bg-[#eef2ff] dark:hover:bg-zinc-800 dark:data-[active]:bg-zinc-800 flex items-center justify-start gap-1 rounded-lg px-2.5 py-2 text-start bg-[#4f46e5] text-white dark:bg-[#6366f1]"
|
||||
variant="default"
|
||||
>
|
||||
<PlusIcon className="w-4 h-4" />
|
||||
New Thread
|
||||
</Button>
|
||||
</ThreadListPrimitive.New>
|
||||
<div className="mt-4 mb-2">
|
||||
<h2 className="text-sm font-medium text-[#475569] dark:text-zinc-300 px-2.5">
|
||||
Recent Chats
|
||||
</h2>
|
||||
</div>
|
||||
<ThreadListPrimitive.Items components={{ ThreadListItem }} />
|
||||
</ThreadListPrimitive.Root>
|
||||
<div>
|
||||
<Link
|
||||
href="https://www.assistant-ui.com/"
|
||||
target="_blank"
|
||||
className="flex justify-center items-center gap-2"
|
||||
>
|
||||
<PlusIcon className="w-4 h-4" />
|
||||
New Thread
|
||||
</Button>
|
||||
</ThreadListPrimitive.New>
|
||||
<div className="mt-4 mb-2">
|
||||
<h2 className="text-sm font-medium text-[#475569] dark:text-zinc-300 px-2.5">Recent Chats</h2>
|
||||
<h1 className="text-sm text-[#475569] dark:text-zinc-300 text-center">
|
||||
built using
|
||||
</h1>
|
||||
<ThemeAwareLogo width={24} height={24} isDarkMode={isDarkMode} />
|
||||
<p className="text-md font-bold dark:text-zinc-300">
|
||||
assistant-ui
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
<ThreadListPrimitive.Items components={{ ThreadListItem }} />
|
||||
</ThreadListPrimitive.Root>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -185,19 +222,20 @@ const ThreadWelcome: FC = () => {
|
||||
<div className="flex w-full max-w-[var(--thread-max-width)] flex-grow flex-col">
|
||||
<div className="flex w-full flex-grow flex-col items-center justify-start h-[calc(100vh-23rem)] md:h-[calc(100vh-18rem)]">
|
||||
<div className="flex flex-col items-center justify-center h-full">
|
||||
<div className="text-5xl font-bold text-[#1e293b] dark:text-white mb-2">
|
||||
Mem0 Demo
|
||||
<div className="text-2xl md:text-4xl font-bold text-[#1e293b] dark:text-white mb-2">
|
||||
Mem0 - ChatGPT with memory
|
||||
</div>
|
||||
<p className="text-center text-sm text-[#1e293b] dark:text-white mb-2 w-3/4">
|
||||
A personalized AI chat app powered by Mem0 that remembers your preferences, facts, and memories.
|
||||
A personalized AI chat app powered by Mem0 that remembers your
|
||||
preferences, facts, and memories.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<p className="mt-4 font-medium text-[#1e293b] dark:text-white">
|
||||
<p className="mt-4 font-medium text-[#1e293b] dark:text-white">
|
||||
How can I help you today?
|
||||
</p>
|
||||
<ThreadWelcomeSuggestions />
|
||||
<ThreadWelcomeSuggestions />
|
||||
</div>
|
||||
</div>
|
||||
</ThreadPrimitive.Empty>
|
||||
@@ -212,21 +250,27 @@ const ThreadWelcomeSuggestions: FC = () => {
|
||||
prompt="I like to travel to "
|
||||
method="replace"
|
||||
>
|
||||
<span className="line-clamp-2 text-ellipsis text-sm font-semibold">Travel</span>
|
||||
<span className="line-clamp-2 text-ellipsis text-sm font-semibold">
|
||||
Travel
|
||||
</span>
|
||||
</ThreadPrimitive.Suggestion>
|
||||
<ThreadPrimitive.Suggestion
|
||||
className="hover:bg-[#eef2ff] dark:hover:bg-zinc-800 flex max-w-sm grow basis-0 flex-col items-center justify-center rounded-[2rem] border border-[#e2e8f0] dark:border-zinc-700 p-3 transition-colors ease-in"
|
||||
prompt="I like to eat "
|
||||
method="replace"
|
||||
>
|
||||
<span className="line-clamp-2 text-ellipsis text-sm font-semibold">Food</span>
|
||||
<span className="line-clamp-2 text-ellipsis text-sm font-semibold">
|
||||
Food
|
||||
</span>
|
||||
</ThreadPrimitive.Suggestion>
|
||||
<ThreadPrimitive.Suggestion
|
||||
className="hover:bg-[#eef2ff] dark:hover:bg-zinc-800 flex max-w-sm grow basis-0 flex-col items-center justify-center rounded-[2rem] border border-[#e2e8f0] dark:border-zinc-700 p-3 transition-colors ease-in"
|
||||
prompt="I am working on "
|
||||
method="replace"
|
||||
>
|
||||
<span className="line-clamp-2 text-ellipsis text-sm font-semibold">Project details</span>
|
||||
<span className="line-clamp-2 text-ellipsis text-sm font-semibold">
|
||||
Project details
|
||||
</span>
|
||||
</ThreadPrimitive.Suggestion>
|
||||
</div>
|
||||
);
|
||||
@@ -335,12 +379,12 @@ const EditComposer: FC = () => {
|
||||
const AssistantMessage: FC = () => {
|
||||
const content = useMessage((m) => m.content);
|
||||
const markdownText = React.useMemo(() => {
|
||||
if (!content) return '';
|
||||
if (typeof content === 'string') return content;
|
||||
if (Array.isArray(content) && content.length > 0 && 'text' in content[0]) {
|
||||
return content[0].text || '';
|
||||
if (!content) return "";
|
||||
if (typeof content === "string") return content;
|
||||
if (Array.isArray(content) && content.length > 0 && "text" in content[0]) {
|
||||
return content[0].text || "";
|
||||
}
|
||||
return '';
|
||||
return "";
|
||||
}, [content]);
|
||||
|
||||
return (
|
||||
@@ -350,7 +394,7 @@ const AssistantMessage: FC = () => {
|
||||
<MarkdownRenderer
|
||||
markdownText={markdownText}
|
||||
showCopyButton={true}
|
||||
isDarkMode={document.documentElement.classList.contains('dark')}
|
||||
isDarkMode={document.documentElement.classList.contains("dark")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -400,7 +444,10 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
||||
return (
|
||||
<BranchPickerPrimitive.Root
|
||||
hideWhenSingleBranch
|
||||
className={cn("text-[#475569] dark:text-zinc-300 inline-flex items-center text-xs", className)}
|
||||
className={cn(
|
||||
"text-[#475569] dark:text-zinc-300 inline-flex items-center text-xs",
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<BranchPickerPrimitive.Previous asChild>
|
||||
@@ -428,7 +475,13 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
||||
|
||||
const CircleStopIcon = () => {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" width="16" height="16">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
fill="currentColor"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<rect width="10" height="10" x="3" y="3" rx="2" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
6
examples/mem0-demo/public/images/assistant-ui-dark.svg
Normal file
6
examples/mem0-demo/public/images/assistant-ui-dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-messages-square">
|
||||
<path d="M14 9a2 2 0 0 1-2 2H6l-4 4V4c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2z">
|
||||
</path>
|
||||
<path d="M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1">
|
||||
</path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 371 B |
6
examples/mem0-demo/public/images/assistant-ui.svg
Normal file
6
examples/mem0-demo/public/images/assistant-ui.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-messages-square">
|
||||
<path d="M14 9a2 2 0 0 1-2 2H6l-4 4V4c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2z">
|
||||
</path>
|
||||
<path d="M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1">
|
||||
</path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 378 B |
Reference in New Issue
Block a user