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.
Files changed (16) hide show
  1. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/.gitignore +2 -0
  2. alpha_avatar_plugins_memory-0.6.2/PKG-INFO +176 -0
  3. alpha_avatar_plugins_memory-0.6.2/README.md +149 -0
  4. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/__init__.py +10 -10
  5. 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
  6. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/runner/lancedb_runner.py +39 -3
  7. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/runner/qdrant_runner.py +39 -3
  8. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/version.py +1 -1
  9. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/pyproject.toml +2 -3
  10. alpha_avatar_plugins_memory-0.6.0/PKG-INFO +0 -54
  11. alpha_avatar_plugins_memory-0.6.0/README.md +0 -26
  12. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/log.py +0 -0
  13. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/memory_markdown.py +0 -0
  14. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/memory_op.py +0 -0
  15. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/memory_prompts.py +0 -0
  16. {alpha_avatar_plugins_memory-0.6.0 → alpha_avatar_plugins_memory-0.6.2}/alphaavatar/plugins/memory/runner/__init__.py +0 -0
@@ -179,3 +179,5 @@ pyrightconfig.json
179
179
  # Database files
180
180
  *.db
181
181
  .alphaavatar_workspace
182
+
183
+ docs/releases/.generated/
@@ -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.utils.files.work_dirs import UserPath
17
+ from alphaavatar.agents.runtime import SessionRuntime
18
18
 
19
19
  from .log import logger
20
- from .memory_langchain import MemoryLangchain
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 MemoryLangchainPlugin(AvatarPlugin):
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
- user_path: UserPath,
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
- ) -> MemoryLangchain:
43
+ ) -> MemoryRuntime:
44
44
  try:
45
- return MemoryLangchain(
46
- user_path=user_path,
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=memory_init_config,
50
+ **memory_init_config,
51
51
  )
52
52
  except Exception as e:
53
- raise ImportError(f"Failed to initialize MemoryLangchain plugin: {e}") from e
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
- MemoryLangchainPlugin(),
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.utils import format_current_time
36
- from alphaavatar.agents.utils.files.work_dirs import UserPath
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 MemoryInitConfig(BaseModel):
313
- openai_model: str = Field(default="gpt-4o-mini")
314
- temperature: float = Field(default=0.0)
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 MemoryLangchain(MemoryBase):
320
+ class MemoryRuntime(MemoryBase):
318
321
  def __init__(
319
322
  self,
320
323
  *,
321
- user_path: UserPath,
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
- memory_init_config: dict[str, Any] | None = None,
328
+ provider: dict[str, Any] | None = None,
329
+ **kwargs,
326
330
  ) -> None:
327
331
  super().__init__(
328
- user_path=user_path,
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._memory_init_config = (
335
- MemoryInitConfig(**memory_init_config) if memory_init_config else MemoryInitConfig()
338
+ self._provider_config = (
339
+ MemoryProviderConfig(**provider) if provider else MemoryProviderConfig()
336
340
  )
337
341
 
338
- llm = ChatOpenAI(
339
- model=self._memory_init_config.openai_model,
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._delta_llm = llm.with_structured_output(MemoryDelta)
344
- self._conversation_delta_chain = CONVERSATION_DELTA_PROMPT | self._delta_llm
345
- self._tool_delta_chain = TOOL_DELTA_PROMPT | self._delta_llm
346
- self._executor = get_job_context().inference_executor
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
- @property
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
- try:
374
- return await asyncio.wait_for(
375
- self._conversation_delta_chain.ainvoke(payload), timeout=timeout
376
- ) # type: ignore
377
- except asyncio.TimeoutError:
378
- logger.warning("[Memory] conversation delta extraction timeout")
379
- return MemoryDelta()
380
- except Exception:
381
- logger.exception("[Memory] conversation delta extraction failed")
382
- return MemoryDelta()
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
- try:
395
- return await asyncio.wait_for(self._tool_delta_chain.ainvoke(payload), timeout=timeout) # type: ignore
396
- except asyncio.TimeoutError:
397
- logger.warning("[Memory] tool delta extraction timeout")
398
- return MemoryDelta()
399
- except Exception:
400
- logger.exception("[Memory] tool delta extraction failed")
401
- return MemoryDelta()
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 = format_current_time().time_str
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._avatar_memory_path,
668
- session_memory_path=self.working_dir,
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.utils.vdb import embedding, lancedb
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 = embedding.get_model(**config)
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.utils.vdb import embedding, qdrant
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 = embedding.get_model(**config)
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")),
@@ -11,4 +11,4 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- __version__ = "0.6.0"
14
+ __version__ = "0.6.2"
@@ -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.10"
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) |