alpha-avatar-plugins-memory 0.6.0__tar.gz → 0.6.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/.gitignore +2 -0
- alpha_avatar_plugins_memory-0.6.2/PKG-INFO +176 -0
- alpha_avatar_plugins_memory-0.6.2/README.md +149 -0
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/__init__.py +10 -10
- alpha_avatar_plugins_memory-0.6.0/alphaavatar/plugins/memory/memory_langchain.py → alpha_avatar_plugins_memory-0.6.2/alphaavatar/plugins/memory/memory_runtime.py +99 -44
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/runner/lancedb_runner.py +39 -3
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/runner/qdrant_runner.py +39 -3
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/version.py +1 -1
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/pyproject.toml +2 -3
- alpha_avatar_plugins_memory-0.6.0/PKG-INFO +0 -54
- alpha_avatar_plugins_memory-0.6.0/README.md +0 -26
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/log.py +0 -0
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/memory_markdown.py +0 -0
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/memory_op.py +0 -0
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/memory_prompts.py +0 -0
- {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/runner/__init__.py +0 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: alpha-avatar-plugins-memory
|
|
3
|
+
Version: 0.6.2
|
|
4
|
+
Summary: AlphaAvatar Framework plugin for memory service
|
|
5
|
+
Project-URL: Source, https://github.com/AlphaAvatar/AlphaAvatar
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Keywords: AI,agents,langchain,llm,memory
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
17
|
+
Classifier: Topic :: Multimedia :: Video
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: <3.12,>=3.11
|
|
20
|
+
Requires-Dist: lancedb==0.30.2
|
|
21
|
+
Requires-Dist: langchain-community
|
|
22
|
+
Requires-Dist: langchain-core
|
|
23
|
+
Requires-Dist: langchain-qdrant
|
|
24
|
+
Requires-Dist: qdrant-client
|
|
25
|
+
Requires-Dist: torchaudio>=0.10.1
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# 🧠 Memory Plugin for AlphaAvatar
|
|
29
|
+
|
|
30
|
+
> Give AlphaAvatar the ability to **remember you** — across conversations, sessions, and time.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🤔 What is the Memory Plugin?
|
|
35
|
+
|
|
36
|
+
Imagine talking to an assistant that forgets everything you said the moment you close the app. Frustrating, right?
|
|
37
|
+
|
|
38
|
+
The **Memory Plugin** solves this. It allows AlphaAvatar to:
|
|
39
|
+
- Remember your **name, preferences, and habits**
|
|
40
|
+
- Recall **past conversations** and what was discussed
|
|
41
|
+
- Learn from its own **tool usage** (like web searches or documents it read)
|
|
42
|
+
- Get **smarter and more personal** the more you use it
|
|
43
|
+
|
|
44
|
+
Think of it like giving AlphaAvatar a notebook — every important thing gets written down and read back when needed.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 💡 How Does it Work? (Simple Flow)
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
You say something to AlphaAvatar
|
|
52
|
+
↓
|
|
53
|
+
AlphaAvatar picks out important information
|
|
54
|
+
(your name, preferences, facts, decisions)
|
|
55
|
+
↓
|
|
56
|
+
That information gets saved to local storage
|
|
57
|
+
↓
|
|
58
|
+
Next time you start a conversation
|
|
59
|
+
↓
|
|
60
|
+
AlphaAvatar reads its saved memories
|
|
61
|
+
↓
|
|
62
|
+
Responds like it knows you — because it does
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
No setup needed from your side. It works automatically in the background.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## ✨ Features
|
|
70
|
+
|
|
71
|
+
### 🌍 Global Memory (Avatar-wide)
|
|
72
|
+
AlphaAvatar maintains memories across your entire experience — not just one chat window.
|
|
73
|
+
|
|
74
|
+
This includes:
|
|
75
|
+
- Things **you** told it (name, preferences, goals)
|
|
76
|
+
- Things it learned from **external tools** (web searches, documents, research)
|
|
77
|
+
- Things it observed from **its own environment** (what worked, what didn't)
|
|
78
|
+
|
|
79
|
+
### ⚡ Real-time Context Updates
|
|
80
|
+
Memory doesn't just update at the end of a conversation — it updates **while you're talking**. If you mention something new mid-conversation, it gets remembered immediately.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 📦 What Kind of Things Does AlphaAvatar Remember?
|
|
85
|
+
|
|
86
|
+
| Type | Real Example |
|
|
87
|
+
|------|-------------|
|
|
88
|
+
| 👤 Personal facts | "My name is Alex and I live in New York" |
|
|
89
|
+
| ❤️ Preferences | "I like short, direct answers" |
|
|
90
|
+
| 🔍 Research results | Facts found during a DeepResearch session |
|
|
91
|
+
| 📄 Document knowledge | Content from files you uploaded via RAG |
|
|
92
|
+
| 🗓️ Past conversations | Topics and decisions from previous sessions |
|
|
93
|
+
| 🛠️ Tool interactions | Results from MCP tools like Notion or Gmail |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 🔧 Installation
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install alpha-avatar-plugins-memory
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
That's it. The plugin is automatically used when you run AlphaAvatar.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 🗄️ How Memories are Stored
|
|
108
|
+
|
|
109
|
+
AlphaAvatar uses **vector storage** to save memories. This means memories aren't stored as plain text — they're stored in a way that makes them easy to search and retrieve intelligently.
|
|
110
|
+
|
|
111
|
+
### Supported Backends
|
|
112
|
+
|
|
113
|
+
| Backend | What it Does |
|
|
114
|
+
|---------|-------------|
|
|
115
|
+
| **LanceDB** | Saves memories locally on your machine (default) |
|
|
116
|
+
| **Qdrant** | A powerful vector database for storage and retrieval |
|
|
117
|
+
| **LangChain** | The pipeline that extracts and processes memories |
|
|
118
|
+
|
|
119
|
+
By default, everything is stored **locally** — your memories never leave your machine unless you configure a cloud backend.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🔗 How Memory Connects to Other Plugins
|
|
124
|
+
|
|
125
|
+
The Memory plugin doesn't work alone — it's the foundation that other plugins build on:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
Memory Plugin
|
|
129
|
+
├── → Persona Plugin (builds your user profile from memories)
|
|
130
|
+
├── → RAG Plugin (stores document knowledge in memory)
|
|
131
|
+
├── → Reflection* (analyzes memories to improve Avatar behavior)
|
|
132
|
+
└── → Planning* (uses memories to set reminders and goals)
|
|
133
|
+
|
|
134
|
+
* Coming soon
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 🙋 Common Questions
|
|
140
|
+
|
|
141
|
+
**Q: Does memory work across different devices?**
|
|
142
|
+
By default, memory is stored locally. Cross-device sync is not yet supported.
|
|
143
|
+
|
|
144
|
+
**Q: Can I see what AlphaAvatar remembers about me?**
|
|
145
|
+
A memory inspection panel is currently in development.
|
|
146
|
+
|
|
147
|
+
**Q: Can I delete a memory?**
|
|
148
|
+
The ability to query, correct, and delete specific memories is coming soon.
|
|
149
|
+
|
|
150
|
+
**Q: Is my data private?**
|
|
151
|
+
Yes — by default everything is stored locally on your machine using LanceDB.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 🚀 Coming Soon
|
|
156
|
+
|
|
157
|
+
AlphaAvatar's Memory plugin is actively being improved. Here's what's coming:
|
|
158
|
+
|
|
159
|
+
| Feature | Description |
|
|
160
|
+
|---------|-------------|
|
|
161
|
+
| 🎤 Voice Memory | Remember things said during voice conversations |
|
|
162
|
+
| 👁️ Visual Memory | Extract memories from images, screenshots, and camera frames |
|
|
163
|
+
| 😊 Face-based Memory | Remember users by their face using facial recognition |
|
|
164
|
+
| 🕸️ Graph Memory | Understand relationships between memories (people, events, goals) |
|
|
165
|
+
| 🔒 Memory Privacy Controls | Let users view, edit, export, or delete their memories |
|
|
166
|
+
| 👥 Multi-user Memory | Separate memories for multiple users in the same session |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 📚 Related Links
|
|
171
|
+
|
|
172
|
+
- [Qdrant Documentation](https://qdrant.tech)
|
|
173
|
+
- [LangChain Documentation](https://www.langchain.com)
|
|
174
|
+
- [AlphaAvatar ROADMAP — Memory Section](https://github.com/AlphaAvatar/AlphaAvatar/blob/main/ROADMAP.md#-memory)
|
|
175
|
+
- [Persona Plugin](https://github.com/AlphaAvatar/AlphaAvatar/blob/main/avatar-plugins/avatar-plugins-persona/README.md)
|
|
176
|
+
-
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# 🧠 Memory Plugin for AlphaAvatar
|
|
2
|
+
|
|
3
|
+
> Give AlphaAvatar the ability to **remember you** — across conversations, sessions, and time.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🤔 What is the Memory Plugin?
|
|
8
|
+
|
|
9
|
+
Imagine talking to an assistant that forgets everything you said the moment you close the app. Frustrating, right?
|
|
10
|
+
|
|
11
|
+
The **Memory Plugin** solves this. It allows AlphaAvatar to:
|
|
12
|
+
- Remember your **name, preferences, and habits**
|
|
13
|
+
- Recall **past conversations** and what was discussed
|
|
14
|
+
- Learn from its own **tool usage** (like web searches or documents it read)
|
|
15
|
+
- Get **smarter and more personal** the more you use it
|
|
16
|
+
|
|
17
|
+
Think of it like giving AlphaAvatar a notebook — every important thing gets written down and read back when needed.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 💡 How Does it Work? (Simple Flow)
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
You say something to AlphaAvatar
|
|
25
|
+
↓
|
|
26
|
+
AlphaAvatar picks out important information
|
|
27
|
+
(your name, preferences, facts, decisions)
|
|
28
|
+
↓
|
|
29
|
+
That information gets saved to local storage
|
|
30
|
+
↓
|
|
31
|
+
Next time you start a conversation
|
|
32
|
+
↓
|
|
33
|
+
AlphaAvatar reads its saved memories
|
|
34
|
+
↓
|
|
35
|
+
Responds like it knows you — because it does
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
No setup needed from your side. It works automatically in the background.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## ✨ Features
|
|
43
|
+
|
|
44
|
+
### 🌍 Global Memory (Avatar-wide)
|
|
45
|
+
AlphaAvatar maintains memories across your entire experience — not just one chat window.
|
|
46
|
+
|
|
47
|
+
This includes:
|
|
48
|
+
- Things **you** told it (name, preferences, goals)
|
|
49
|
+
- Things it learned from **external tools** (web searches, documents, research)
|
|
50
|
+
- Things it observed from **its own environment** (what worked, what didn't)
|
|
51
|
+
|
|
52
|
+
### ⚡ Real-time Context Updates
|
|
53
|
+
Memory doesn't just update at the end of a conversation — it updates **while you're talking**. If you mention something new mid-conversation, it gets remembered immediately.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 📦 What Kind of Things Does AlphaAvatar Remember?
|
|
58
|
+
|
|
59
|
+
| Type | Real Example |
|
|
60
|
+
|------|-------------|
|
|
61
|
+
| 👤 Personal facts | "My name is Alex and I live in New York" |
|
|
62
|
+
| ❤️ Preferences | "I like short, direct answers" |
|
|
63
|
+
| 🔍 Research results | Facts found during a DeepResearch session |
|
|
64
|
+
| 📄 Document knowledge | Content from files you uploaded via RAG |
|
|
65
|
+
| 🗓️ Past conversations | Topics and decisions from previous sessions |
|
|
66
|
+
| 🛠️ Tool interactions | Results from MCP tools like Notion or Gmail |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 🔧 Installation
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install alpha-avatar-plugins-memory
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
That's it. The plugin is automatically used when you run AlphaAvatar.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 🗄️ How Memories are Stored
|
|
81
|
+
|
|
82
|
+
AlphaAvatar uses **vector storage** to save memories. This means memories aren't stored as plain text — they're stored in a way that makes them easy to search and retrieve intelligently.
|
|
83
|
+
|
|
84
|
+
### Supported Backends
|
|
85
|
+
|
|
86
|
+
| Backend | What it Does |
|
|
87
|
+
|---------|-------------|
|
|
88
|
+
| **LanceDB** | Saves memories locally on your machine (default) |
|
|
89
|
+
| **Qdrant** | A powerful vector database for storage and retrieval |
|
|
90
|
+
| **LangChain** | The pipeline that extracts and processes memories |
|
|
91
|
+
|
|
92
|
+
By default, everything is stored **locally** — your memories never leave your machine unless you configure a cloud backend.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 🔗 How Memory Connects to Other Plugins
|
|
97
|
+
|
|
98
|
+
The Memory plugin doesn't work alone — it's the foundation that other plugins build on:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
Memory Plugin
|
|
102
|
+
├── → Persona Plugin (builds your user profile from memories)
|
|
103
|
+
├── → RAG Plugin (stores document knowledge in memory)
|
|
104
|
+
├── → Reflection* (analyzes memories to improve Avatar behavior)
|
|
105
|
+
└── → Planning* (uses memories to set reminders and goals)
|
|
106
|
+
|
|
107
|
+
* Coming soon
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 🙋 Common Questions
|
|
113
|
+
|
|
114
|
+
**Q: Does memory work across different devices?**
|
|
115
|
+
By default, memory is stored locally. Cross-device sync is not yet supported.
|
|
116
|
+
|
|
117
|
+
**Q: Can I see what AlphaAvatar remembers about me?**
|
|
118
|
+
A memory inspection panel is currently in development.
|
|
119
|
+
|
|
120
|
+
**Q: Can I delete a memory?**
|
|
121
|
+
The ability to query, correct, and delete specific memories is coming soon.
|
|
122
|
+
|
|
123
|
+
**Q: Is my data private?**
|
|
124
|
+
Yes — by default everything is stored locally on your machine using LanceDB.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 🚀 Coming Soon
|
|
129
|
+
|
|
130
|
+
AlphaAvatar's Memory plugin is actively being improved. Here's what's coming:
|
|
131
|
+
|
|
132
|
+
| Feature | Description |
|
|
133
|
+
|---------|-------------|
|
|
134
|
+
| 🎤 Voice Memory | Remember things said during voice conversations |
|
|
135
|
+
| 👁️ Visual Memory | Extract memories from images, screenshots, and camera frames |
|
|
136
|
+
| 😊 Face-based Memory | Remember users by their face using facial recognition |
|
|
137
|
+
| 🕸️ Graph Memory | Understand relationships between memories (people, events, goals) |
|
|
138
|
+
| 🔒 Memory Privacy Controls | Let users view, edit, export, or delete their memories |
|
|
139
|
+
| 👥 Multi-user Memory | Separate memories for multiple users in the same session |
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 📚 Related Links
|
|
144
|
+
|
|
145
|
+
- [Qdrant Documentation](https://qdrant.tech)
|
|
146
|
+
- [LangChain Documentation](https://www.langchain.com)
|
|
147
|
+
- [AlphaAvatar ROADMAP — Memory Section](https://github.com/AlphaAvatar/AlphaAvatar/blob/main/ROADMAP.md#-memory)
|
|
148
|
+
- [Persona Plugin](https://github.com/AlphaAvatar/AlphaAvatar/blob/main/avatar-plugins/avatar-plugins-persona/README.md)
|
|
149
|
+
-
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
import os
|
|
15
15
|
|
|
16
16
|
from alphaavatar.agents import AvatarModule, AvatarPlugin
|
|
17
|
-
from alphaavatar.agents.
|
|
17
|
+
from alphaavatar.agents.runtime import SessionRuntime
|
|
18
18
|
|
|
19
19
|
from .log import logger
|
|
20
|
-
from .
|
|
20
|
+
from .memory_runtime import MemoryRuntime
|
|
21
21
|
from .version import __version__
|
|
22
22
|
|
|
23
23
|
__all__ = [
|
|
@@ -25,7 +25,7 @@ __all__ = [
|
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class
|
|
28
|
+
class MemoryPlugin(AvatarPlugin):
|
|
29
29
|
def __init__(self) -> None:
|
|
30
30
|
super().__init__(__name__, __version__, __package__, logger) # type: ignore
|
|
31
31
|
|
|
@@ -33,24 +33,24 @@ class MemoryLangchainPlugin(AvatarPlugin):
|
|
|
33
33
|
|
|
34
34
|
def get_plugin(
|
|
35
35
|
self,
|
|
36
|
-
|
|
36
|
+
session_runtime: SessionRuntime,
|
|
37
37
|
memory_search_context: int,
|
|
38
38
|
memory_recall_num: int,
|
|
39
39
|
maximum_memory_num: int,
|
|
40
40
|
memory_init_config: dict,
|
|
41
41
|
*args,
|
|
42
42
|
**kwargs,
|
|
43
|
-
) ->
|
|
43
|
+
) -> MemoryRuntime:
|
|
44
44
|
try:
|
|
45
|
-
return
|
|
46
|
-
|
|
45
|
+
return MemoryRuntime(
|
|
46
|
+
session_runtime=session_runtime,
|
|
47
47
|
memory_search_context=memory_search_context,
|
|
48
48
|
memory_recall_num=memory_recall_num,
|
|
49
49
|
maximum_memory_num=maximum_memory_num,
|
|
50
|
-
memory_init_config
|
|
50
|
+
**memory_init_config,
|
|
51
51
|
)
|
|
52
52
|
except Exception as e:
|
|
53
|
-
raise ImportError(f"Failed to initialize
|
|
53
|
+
raise ImportError(f"Failed to initialize MemoryRuntime plugin: {e}") from e
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
def bootstrap_inference_runners() -> None:
|
|
@@ -82,7 +82,7 @@ def bootstrap_inference_runners() -> None:
|
|
|
82
82
|
AvatarPlugin.register_avatar_plugin(
|
|
83
83
|
AvatarModule.MEMORY,
|
|
84
84
|
"default",
|
|
85
|
-
|
|
85
|
+
MemoryPlugin(),
|
|
86
86
|
)
|
|
87
87
|
|
|
88
88
|
# Runner bootstrap register
|
|
@@ -19,7 +19,6 @@ import re
|
|
|
19
19
|
from typing import Any
|
|
20
20
|
|
|
21
21
|
from langchain_core.prompts import ChatPromptTemplate
|
|
22
|
-
from langchain_openai import ChatOpenAI
|
|
23
22
|
from livekit.agents.job import get_job_context
|
|
24
23
|
from livekit.agents.llm import ChatItem
|
|
25
24
|
from pydantic import BaseModel, Field
|
|
@@ -32,8 +31,11 @@ from alphaavatar.agents.memory import (
|
|
|
32
31
|
MemoryType,
|
|
33
32
|
VectorRunnerOP,
|
|
34
33
|
)
|
|
35
|
-
from alphaavatar.agents.
|
|
36
|
-
|
|
34
|
+
from alphaavatar.agents.providers import (
|
|
35
|
+
ProviderGateway,
|
|
36
|
+
ProvidersConfig,
|
|
37
|
+
)
|
|
38
|
+
from alphaavatar.agents.runtime import SessionRuntime
|
|
37
39
|
|
|
38
40
|
from .log import logger
|
|
39
41
|
from .memory_markdown import save_memory_items_to_markdown
|
|
@@ -309,45 +311,46 @@ def _select_by_priority(
|
|
|
309
311
|
return picked
|
|
310
312
|
|
|
311
313
|
|
|
312
|
-
class
|
|
313
|
-
|
|
314
|
-
|
|
314
|
+
class MemoryProviderConfig(BaseModel):
|
|
315
|
+
conversation_delta_task: str = "memory.conversation_delta"
|
|
316
|
+
tool_delta_task: str = "memory.tool_delta"
|
|
317
|
+
gateway: ProvidersConfig = Field(default_factory=ProvidersConfig)
|
|
315
318
|
|
|
316
319
|
|
|
317
|
-
class
|
|
320
|
+
class MemoryRuntime(MemoryBase):
|
|
318
321
|
def __init__(
|
|
319
322
|
self,
|
|
320
323
|
*,
|
|
321
|
-
|
|
324
|
+
session_runtime: SessionRuntime,
|
|
322
325
|
memory_search_context: int = 3,
|
|
323
326
|
memory_recall_num: int = 10,
|
|
324
327
|
maximum_memory_num: int = 24,
|
|
325
|
-
|
|
328
|
+
provider: dict[str, Any] | None = None,
|
|
329
|
+
**kwargs,
|
|
326
330
|
) -> None:
|
|
327
331
|
super().__init__(
|
|
328
|
-
|
|
332
|
+
session_runtime=session_runtime,
|
|
329
333
|
memory_search_context=memory_search_context,
|
|
330
334
|
memory_recall_num=memory_recall_num,
|
|
331
335
|
maximum_memory_num=maximum_memory_num,
|
|
332
336
|
)
|
|
333
337
|
|
|
334
|
-
self.
|
|
335
|
-
|
|
338
|
+
self._provider_config = (
|
|
339
|
+
MemoryProviderConfig(**provider) if provider else MemoryProviderConfig()
|
|
336
340
|
)
|
|
337
341
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
temperature=self._memory_init_config.temperature,
|
|
341
|
-
) # type: ignore
|
|
342
|
+
self._conversation_delta_task = self._provider_config.conversation_delta_task
|
|
343
|
+
self._tool_delta_task = self._provider_config.tool_delta_task
|
|
342
344
|
|
|
343
|
-
self.
|
|
344
|
-
self.
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
self._provider_gateway = ProviderGateway(self._provider_config.gateway)
|
|
346
|
+
self._provider_gateway.validate_tasks(
|
|
347
|
+
[
|
|
348
|
+
self._conversation_delta_task,
|
|
349
|
+
self._tool_delta_task,
|
|
350
|
+
]
|
|
351
|
+
)
|
|
347
352
|
|
|
348
|
-
|
|
349
|
-
def memory_init_config(self) -> MemoryInitConfig:
|
|
350
|
-
return self._memory_init_config
|
|
353
|
+
self._executor = get_job_context().inference_executor
|
|
351
354
|
|
|
352
355
|
@property
|
|
353
356
|
def inference_method(self) -> str:
|
|
@@ -360,45 +363,94 @@ class MemoryLangchain(MemoryBase):
|
|
|
360
363
|
)
|
|
361
364
|
return method
|
|
362
365
|
|
|
366
|
+
async def _safe_ainvoke_delta(
|
|
367
|
+
self,
|
|
368
|
+
*,
|
|
369
|
+
task_name: str,
|
|
370
|
+
prompt,
|
|
371
|
+
payload: dict[str, Any],
|
|
372
|
+
metadata: dict[str, Any],
|
|
373
|
+
timeout: float = 12.0,
|
|
374
|
+
) -> MemoryDelta:
|
|
375
|
+
try:
|
|
376
|
+
result = await asyncio.wait_for(
|
|
377
|
+
self._provider_gateway.ainvoke_structured(
|
|
378
|
+
task_name=task_name,
|
|
379
|
+
prompt=prompt,
|
|
380
|
+
payload=payload,
|
|
381
|
+
output_schema=MemoryDelta,
|
|
382
|
+
metadata=metadata,
|
|
383
|
+
),
|
|
384
|
+
timeout=timeout,
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
if isinstance(result.output, MemoryDelta):
|
|
388
|
+
return result.output
|
|
389
|
+
|
|
390
|
+
return MemoryDelta.model_validate(result.output)
|
|
391
|
+
|
|
392
|
+
except asyncio.TimeoutError:
|
|
393
|
+
logger.warning("[Memory] delta extraction timeout task=%s", task_name)
|
|
394
|
+
return MemoryDelta()
|
|
395
|
+
except Exception:
|
|
396
|
+
logger.exception("[Memory] delta extraction failed task=%s", task_name)
|
|
397
|
+
return MemoryDelta()
|
|
398
|
+
|
|
363
399
|
async def _safe_ainvoke_conversation_delta(
|
|
364
400
|
self,
|
|
365
401
|
*,
|
|
366
402
|
message_content: str,
|
|
403
|
+
memory_cache: MemoryCache,
|
|
367
404
|
timeout: float = 12.0,
|
|
368
405
|
) -> MemoryDelta:
|
|
369
406
|
payload = {
|
|
370
407
|
"type": MemoryType.CONVERSATION,
|
|
371
408
|
"message_content": message_content,
|
|
372
409
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
410
|
+
|
|
411
|
+
return await self._safe_ainvoke_delta(
|
|
412
|
+
task_name=self._conversation_delta_task,
|
|
413
|
+
prompt=CONVERSATION_DELTA_PROMPT,
|
|
414
|
+
payload=payload,
|
|
415
|
+
metadata={
|
|
416
|
+
"provider_dir": memory_cache.provider_dir,
|
|
417
|
+
"plugin": "memory",
|
|
418
|
+
"component": "memory_delta_extractor",
|
|
419
|
+
"operation": "conversation_delta",
|
|
420
|
+
"session_id": memory_cache.session_id,
|
|
421
|
+
"user_or_tool_id": memory_cache.user_or_tool_id,
|
|
422
|
+
"memory_type": str(memory_cache.type),
|
|
423
|
+
},
|
|
424
|
+
timeout=timeout,
|
|
425
|
+
)
|
|
383
426
|
|
|
384
427
|
async def _safe_ainvoke_tool_delta(
|
|
385
428
|
self,
|
|
386
429
|
*,
|
|
387
430
|
message_content: str,
|
|
431
|
+
memory_cache: MemoryCache,
|
|
388
432
|
timeout: float = 12.0,
|
|
389
433
|
) -> MemoryDelta:
|
|
390
434
|
payload = {
|
|
391
435
|
"type": MemoryType.TOOLS,
|
|
392
436
|
"message_content": message_content,
|
|
393
437
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
438
|
+
|
|
439
|
+
return await self._safe_ainvoke_delta(
|
|
440
|
+
task_name=self._tool_delta_task,
|
|
441
|
+
prompt=TOOL_DELTA_PROMPT,
|
|
442
|
+
payload=payload,
|
|
443
|
+
metadata={
|
|
444
|
+
"provider_dir": memory_cache.provider_dir,
|
|
445
|
+
"plugin": "memory",
|
|
446
|
+
"component": "memory_delta_extractor",
|
|
447
|
+
"operation": "tool_delta",
|
|
448
|
+
"session_id": memory_cache.session_id,
|
|
449
|
+
"user_or_tool_id": memory_cache.user_or_tool_id,
|
|
450
|
+
"memory_type": str(memory_cache.type),
|
|
451
|
+
},
|
|
452
|
+
timeout=timeout,
|
|
453
|
+
)
|
|
402
454
|
|
|
403
455
|
def _apply_delta_to_bucket(
|
|
404
456
|
self,
|
|
@@ -408,7 +460,7 @@ class MemoryLangchain(MemoryBase):
|
|
|
408
460
|
memory_cache: MemoryCache,
|
|
409
461
|
user_or_tool_memory_type: MemoryType,
|
|
410
462
|
):
|
|
411
|
-
updated_time =
|
|
463
|
+
updated_time = memory_cache.time
|
|
412
464
|
assistant_memories: list[MemoryItem] = []
|
|
413
465
|
target_memories: list[MemoryItem] = []
|
|
414
466
|
|
|
@@ -563,16 +615,19 @@ class MemoryLangchain(MemoryBase):
|
|
|
563
615
|
conversation_delta, tool_delta = await asyncio.gather(
|
|
564
616
|
self._safe_ainvoke_conversation_delta(
|
|
565
617
|
message_content=message_content,
|
|
618
|
+
memory_cache=cache,
|
|
566
619
|
timeout=30.0,
|
|
567
620
|
),
|
|
568
621
|
self._safe_ainvoke_tool_delta(
|
|
569
622
|
message_content=message_content,
|
|
623
|
+
memory_cache=cache,
|
|
570
624
|
timeout=30.0,
|
|
571
625
|
),
|
|
572
626
|
)
|
|
573
627
|
else:
|
|
574
628
|
conversation_delta = await self._safe_ainvoke_conversation_delta(
|
|
575
629
|
message_content=message_content,
|
|
630
|
+
memory_cache=cache,
|
|
576
631
|
timeout=30.0,
|
|
577
632
|
)
|
|
578
633
|
tool_delta = None
|
|
@@ -664,8 +719,8 @@ class MemoryLangchain(MemoryBase):
|
|
|
664
719
|
## 5.1 Save to local .md file for backup/debug
|
|
665
720
|
try:
|
|
666
721
|
md_result = save_memory_items_to_markdown(
|
|
667
|
-
avatar_memory_path=self.
|
|
668
|
-
session_memory_path=self.
|
|
722
|
+
avatar_memory_path=self.session_runtime.avatar_path.memory_dir,
|
|
723
|
+
session_memory_path=self.session_runtime.session_path.memory_dir,
|
|
669
724
|
memory_items=memory_items,
|
|
670
725
|
)
|
|
671
726
|
logger.info(f"Memory local markdown backup success: {md_result}")
|
|
@@ -13,11 +13,14 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import json
|
|
15
15
|
import os
|
|
16
|
+
from typing import Any
|
|
16
17
|
|
|
17
18
|
from livekit.agents.inference_runner import _InferenceRunner
|
|
18
19
|
|
|
19
20
|
from alphaavatar.agents.memory import VectorRunnerOP
|
|
20
|
-
from alphaavatar.agents.
|
|
21
|
+
from alphaavatar.agents.providers import ProviderKind, ProviderTaskConfig
|
|
22
|
+
from alphaavatar.agents.providers.embedding import create_embedding_model
|
|
23
|
+
from alphaavatar.agents.utils.vdb import lancedb
|
|
21
24
|
|
|
22
25
|
|
|
23
26
|
class LanceDBRunner(_InferenceRunner):
|
|
@@ -174,6 +177,39 @@ class LanceDBRunner(_InferenceRunner):
|
|
|
174
177
|
|
|
175
178
|
return result
|
|
176
179
|
|
|
180
|
+
#
|
|
181
|
+
# Runner Interface
|
|
182
|
+
#
|
|
183
|
+
|
|
184
|
+
def _get_vdb_config(self, config: dict[str, Any]) -> dict[str, Any]:
|
|
185
|
+
vdb_config = dict(config)
|
|
186
|
+
vdb_config.pop("embedding", None)
|
|
187
|
+
return vdb_config
|
|
188
|
+
|
|
189
|
+
def _get_memory_embeddings(self, config: dict[str, Any]):
|
|
190
|
+
embedding_config = config.get("embedding")
|
|
191
|
+
|
|
192
|
+
if not embedding_config:
|
|
193
|
+
raise ValueError("`embedding` is required in MEMORY_VDB_CONFIG")
|
|
194
|
+
|
|
195
|
+
provider = embedding_config.get("provider")
|
|
196
|
+
model = embedding_config.get("model")
|
|
197
|
+
extra = embedding_config.get("extra") or {}
|
|
198
|
+
|
|
199
|
+
if not provider:
|
|
200
|
+
raise ValueError("`embedding.provider` is required in MEMORY_VDB_CONFIG")
|
|
201
|
+
if not model:
|
|
202
|
+
raise ValueError("`embedding.model` is required in MEMORY_VDB_CONFIG")
|
|
203
|
+
|
|
204
|
+
task_config = ProviderTaskConfig(
|
|
205
|
+
kind=ProviderKind.EMBEDDING,
|
|
206
|
+
provider=provider,
|
|
207
|
+
model=model,
|
|
208
|
+
extra=extra,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
return create_embedding_model(task_config)
|
|
212
|
+
|
|
177
213
|
def initialize(self) -> None:
|
|
178
214
|
config = os.getenv("MEMORY_VDB_CONFIG", "{}")
|
|
179
215
|
config = json.loads(config)
|
|
@@ -182,9 +218,9 @@ class LanceDBRunner(_InferenceRunner):
|
|
|
182
218
|
if not self._collection_name:
|
|
183
219
|
raise ValueError("collection_name is required in MEMORY_VDB_CONFIG")
|
|
184
220
|
|
|
185
|
-
self._client = lancedb.get_client(**config)
|
|
221
|
+
self._client = lancedb.get_client(**self._get_vdb_config(config))
|
|
186
222
|
|
|
187
|
-
self._embeddings =
|
|
223
|
+
self._embeddings = self._get_memory_embeddings(config)
|
|
188
224
|
embedding_dim = len(self._embeddings.embed_query("dimension-probe"))
|
|
189
225
|
|
|
190
226
|
self._ensure_collection(self._collection_name, embedding_dim)
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import json
|
|
15
15
|
import os
|
|
16
|
+
from typing import Any
|
|
16
17
|
|
|
17
18
|
from langchain_qdrant import QdrantVectorStore
|
|
18
19
|
from livekit.agents.inference_runner import _InferenceRunner
|
|
@@ -27,7 +28,9 @@ from qdrant_client.models import (
|
|
|
27
28
|
)
|
|
28
29
|
|
|
29
30
|
from alphaavatar.agents.memory import VectorRunnerOP
|
|
30
|
-
from alphaavatar.agents.
|
|
31
|
+
from alphaavatar.agents.providers import ProviderKind, ProviderTaskConfig
|
|
32
|
+
from alphaavatar.agents.providers.embedding import create_embedding_model
|
|
33
|
+
from alphaavatar.agents.utils.vdb import qdrant
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
class QdrantRunner(_InferenceRunner):
|
|
@@ -127,6 +130,39 @@ class QdrantRunner(_InferenceRunner):
|
|
|
127
130
|
|
|
128
131
|
return result
|
|
129
132
|
|
|
133
|
+
#
|
|
134
|
+
# Runner Interface
|
|
135
|
+
#
|
|
136
|
+
|
|
137
|
+
def _get_vdb_config(self, config: dict[str, Any]) -> dict[str, Any]:
|
|
138
|
+
vdb_config = dict(config)
|
|
139
|
+
vdb_config.pop("embedding", None)
|
|
140
|
+
return vdb_config
|
|
141
|
+
|
|
142
|
+
def _get_memory_embeddings(self, config: dict[str, Any]):
|
|
143
|
+
embedding_config = config.get("embedding")
|
|
144
|
+
|
|
145
|
+
if not embedding_config:
|
|
146
|
+
raise ValueError("`embedding` is required in MEMORY_VDB_CONFIG")
|
|
147
|
+
|
|
148
|
+
provider = embedding_config.get("provider")
|
|
149
|
+
model = embedding_config.get("model")
|
|
150
|
+
extra = embedding_config.get("extra") or {}
|
|
151
|
+
|
|
152
|
+
if not provider:
|
|
153
|
+
raise ValueError("`embedding.provider` is required in MEMORY_VDB_CONFIG")
|
|
154
|
+
if not model:
|
|
155
|
+
raise ValueError("`embedding.model` is required in MEMORY_VDB_CONFIG")
|
|
156
|
+
|
|
157
|
+
task_config = ProviderTaskConfig(
|
|
158
|
+
kind=ProviderKind.EMBEDDING,
|
|
159
|
+
provider=provider,
|
|
160
|
+
model=model,
|
|
161
|
+
extra=extra,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return create_embedding_model(task_config)
|
|
165
|
+
|
|
130
166
|
def initialize(self) -> None:
|
|
131
167
|
# get config
|
|
132
168
|
config = os.getenv("MEMORY_VDB_CONFIG", "{}")
|
|
@@ -134,10 +170,10 @@ class QdrantRunner(_InferenceRunner):
|
|
|
134
170
|
self._collection_name = config.get("collection_name", None)
|
|
135
171
|
|
|
136
172
|
# init client
|
|
137
|
-
self._client = qdrant.get_client(**config)
|
|
173
|
+
self._client = qdrant.get_client(**self._get_vdb_config(config))
|
|
138
174
|
|
|
139
175
|
# init memory
|
|
140
|
-
self._embeddings =
|
|
176
|
+
self._embeddings = self._get_memory_embeddings(config)
|
|
141
177
|
self._ensure_collection(
|
|
142
178
|
self._collection_name,
|
|
143
179
|
len(self._embeddings.embed_query("dimension-probe")),
|
|
@@ -8,7 +8,7 @@ dynamic = ["version"]
|
|
|
8
8
|
description = "AlphaAvatar Framework plugin for memory service"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
11
|
-
requires-python = ">=3.
|
|
11
|
+
requires-python = ">=3.11,<3.12"
|
|
12
12
|
keywords = ["llm", "agents", "AI", "memory", "langchain"]
|
|
13
13
|
classifiers = [
|
|
14
14
|
"Intended Audience :: Developers",
|
|
@@ -26,9 +26,8 @@ classifiers = [
|
|
|
26
26
|
dependencies = [
|
|
27
27
|
"langchain-core",
|
|
28
28
|
"langchain-community",
|
|
29
|
-
"langchain-openai",
|
|
30
29
|
"qdrant-client",
|
|
31
|
-
"lancedb",
|
|
30
|
+
"lancedb==0.30.2",
|
|
32
31
|
"langchain-qdrant",
|
|
33
32
|
"torchaudio>=0.10.1"
|
|
34
33
|
]
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: alpha-avatar-plugins-memory
|
|
3
|
-
Version: 0.6.0
|
|
4
|
-
Summary: AlphaAvatar Framework plugin for memory service
|
|
5
|
-
Project-URL: Source, https://github.com/AlphaAvatar/AlphaAvatar
|
|
6
|
-
License-Expression: Apache-2.0
|
|
7
|
-
Keywords: AI,agents,langchain,llm,memory
|
|
8
|
-
Classifier: Intended Audience :: Developers
|
|
9
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
-
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
17
|
-
Classifier: Topic :: Multimedia :: Video
|
|
18
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
-
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist: lancedb
|
|
21
|
-
Requires-Dist: langchain-community
|
|
22
|
-
Requires-Dist: langchain-core
|
|
23
|
-
Requires-Dist: langchain-openai
|
|
24
|
-
Requires-Dist: langchain-qdrant
|
|
25
|
-
Requires-Dist: qdrant-client
|
|
26
|
-
Requires-Dist: torchaudio>=0.10.1
|
|
27
|
-
Description-Content-Type: text/markdown
|
|
28
|
-
|
|
29
|
-
# Memory Plugin for AlphaAvatar
|
|
30
|
-
|
|
31
|
-
Support for storing and managing conversational memory within Avatar, with a unified interface to open-source memory frameworks.
|
|
32
|
-
This plugin simplifies memory management so developers don’t need to worry about storage limits, or backend details.
|
|
33
|
-
|
|
34
|
-
## Features
|
|
35
|
-
|
|
36
|
-
* **Global Memory (Avatar-wide):** Retrieval and updates of cross-user, Avatar-level memories. This includes memories derived from automatically identified users as well as memories created through the Avatar’s interactions with external tools and the environment.
|
|
37
|
-
* **Real-time Context Updates:** Memories are written and refreshed on the fly based on the current dialogue context.
|
|
38
|
-
|
|
39
|
-
## Installation
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
pip install alpha-avatar-plugins-memory
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Supported Open-Source Memory Frameworks
|
|
48
|
-
|
|
49
|
-
### Default: **LangChain + Qdrant**
|
|
50
|
-
|
|
51
|
-
| Module | Description | Docs |
|
|
52
|
-
| ---------------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
53
|
-
| **Qdrant** (default) | Combined framework for persona extraction pipelines and vector storage / retrieval. | [Qdrant](https://qdrant.tech) |
|
|
54
|
-
| **LangChain** (default) | Combined framework for persona extraction pipelines and vector storage / retrieval. | [LangChain](https://www.langchain.com) |
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Memory Plugin for AlphaAvatar
|
|
2
|
-
|
|
3
|
-
Support for storing and managing conversational memory within Avatar, with a unified interface to open-source memory frameworks.
|
|
4
|
-
This plugin simplifies memory management so developers don’t need to worry about storage limits, or backend details.
|
|
5
|
-
|
|
6
|
-
## Features
|
|
7
|
-
|
|
8
|
-
* **Global Memory (Avatar-wide):** Retrieval and updates of cross-user, Avatar-level memories. This includes memories derived from automatically identified users as well as memories created through the Avatar’s interactions with external tools and the environment.
|
|
9
|
-
* **Real-time Context Updates:** Memories are written and refreshed on the fly based on the current dialogue context.
|
|
10
|
-
|
|
11
|
-
## Installation
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
pip install alpha-avatar-plugins-memory
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Supported Open-Source Memory Frameworks
|
|
20
|
-
|
|
21
|
-
### Default: **LangChain + Qdrant**
|
|
22
|
-
|
|
23
|
-
| Module | Description | Docs |
|
|
24
|
-
| ---------------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
25
|
-
| **Qdrant** (default) | Combined framework for persona extraction pipelines and vector storage / retrieval. | [Qdrant](https://qdrant.tech) |
|
|
26
|
-
| **LangChain** (default) | Combined framework for persona extraction pipelines and vector storage / retrieval. | [LangChain](https://www.langchain.com) |
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|