Skip to content

Commit 809dde4

Browse files
authored
chore: bump version to v2.0.0 (#716)
## Description <!-- Please include a summary of the changes below; Fill in the issue number that this PR addresses (if applicable); Fill in the related MemOS-Docs repository issue or PR link (if applicable); Mention the person who will review this PR (if you know who it is); Replace (summary), (issue), (docs-issue-or-pr-link), and (reviewer) with the appropriate information. 请在下方填写更改的摘要; 填写此 PR 解决的问题编号(如果适用); 填写相关的 MemOS-Docs 仓库 issue 或 PR 链接(如果适用); 提及将审查此 PR 的人(如果您知道是谁); 替换 (summary)、(issue)、(docs-issue-or-pr-link) 和 (reviewer) 为适当的信息。 --> Summary: (summary) Fix: #(issue) Docs Issue/PR: (docs-issue-or-pr-link) Reviewer: @(reviewer) ## Checklist: - [ ] I have performed a self-review of my own code | 我已自行检查了自己的代码 - [ ] I have commented my code in hard-to-understand areas | 我已在难以理解的地方对代码进行了注释 - [ ] I have added tests that prove my fix is effective or that my feature works | 我已添加测试以证明我的修复有效或功能正常 - [ ] I have created related documentation issue/PR in [MemOS-Docs](https://github.com/MemTensor/MemOS-Docs) (if applicable) | 我已在 [MemOS-Docs](https://github.com/MemTensor/MemOS-Docs) 中创建了相关的文档 issue/PR(如果适用) - [ ] I have linked the issue to this PR (if applicable) | 我已将 issue 链接到此 PR(如果适用) - [ ] I have mentioned the person who will review this PR | 我已提及将审查此 PR 的人
2 parents 42c3d9d + 2f10198 commit 809dde4

File tree

225 files changed

+30565
-4913
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

225 files changed

+30565
-4913
lines changed

.github/workflows/python-tests.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ jobs:
2828
os:
2929
- "ubuntu-latest"
3030
- "windows-latest"
31-
- "macos-13"
3231
- "macos-14"
3332
- "macos-15"
3433
# Ref: https://docs.github.com/en/actions/how-tos/writing-workflows/choosing-where-your-workflow-runs/choosing-the-runner-for-a-job

README.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
MemOS is an open-source **Agent Memory framework** that empowers AI agents with **long-term memory, personality consistency, and contextual recall**. It enables agents to **remember past interactions**, **learn over time**, and **build evolving identities** across sessions.
44

55
Designed for **AI companions, role-playing NPCs, and multi-agent systems**, MemOS provides a unified API for **memory representation, retrieval, and update** — making it the foundation for next-generation **memory-augmented AI agents**.
6+
7+
🆕 **MemOS 2.0** introduces **knowledge base system**, **multi-modal memory** (images & documents), **tool memory** for Agent optimization, **memory feedback mechanism** for precise control, and **enterprise-grade architecture** with Redis Streams scheduler and advanced DB optimizations.
68
<div align="center">
79
<a href="https://memos.openmem.net/">
810
<img src="https://statics.memtensor.com.cn/memos/memos-banner.gif" alt="MemOS Banner">
911
</a>
1012

1113
<h1 align="center">
12-
<img src="https://statics.memtensor.com.cn/logo/memos_color_m.png" alt="MemOS Logo" width="50"/> MemOS 1.0: 星河 (Stellar) <img src="https://img.shields.io/badge/status-Preview-blue" alt="Preview Badge"/>
14+
<img src="https://statics.memtensor.com.cn/logo/memos_color_m.png" alt="MemOS Logo" width="50"/> MemOS 2.0: 星尘(Stardust) <img src="https://img.shields.io/badge/status-Preview-blue" alt="Preview Badge"/>
1315
</h1>
1416

1517
<p>
@@ -60,7 +62,7 @@ Get Free API: [Try API](https://memos-dashboard.openmem.net/quickstart/?source=g
6062

6163
<img src="https://cdn.memtensor.com.cn/img/1762436050812_3tgird_compressed.png" alt="SOTA SCORE">
6264

63-
**MemOS** is an operating system for Large Language Models (LLMs) that enhances them with long-term memory capabilities. It allows LLMs to store, retrieve, and manage information, enabling more context-aware, consistent, and personalized interactions.
65+
**MemOS** is an operating system for Large Language Models (LLMs) that enhances them with long-term memory capabilities. It allows LLMs to store, retrieve, and manage information, enabling more context-aware, consistent, and personalized interactions. **MemOS 2.0** features comprehensive knowledge base management, multi-modal memory support, tool memory for Agent enhancement, and enterprise-grade architecture optimizations.
6466

6567
- **Website**: https://memos.openmem.net/
6668
- **Documentation**: https://memos-docs.openmem.net/home/overview/
@@ -71,7 +73,8 @@ Get Free API: [Try API](https://memos-dashboard.openmem.net/quickstart/?source=g
7173

7274
Stay up to date with the latest MemOS announcements, releases, and community highlights.
7375

74-
76+
- **2025-12-24** - 🎉 **MemOS v2.0: Stardust (星尘) Release**:
77+
Major upgrade featuring comprehensive Knowledge Base system with automatic document/URL parsing and cross-project sharing; Memory feedback mechanism for correction and precise deletion; Multi-modal memory supporting images and charts; Tool Memory to enhance Agent planning; Full architecture upgrade with Redis Streams multi-level queue scheduler and DB optimizations; New streaming/non-streaming Chat interfaces; Complete MCP upgrade; Lightweight deployment modes (quick & full).
7578
- **2025-11-06** - 🎉 MemOS v1.1.3 (Async Memory & Preference):
7679
Millisecond-level async memory add (support plain-text-memory and
7780
preference memory); enhanced BM25, graph recall, and mixture search; full
@@ -114,7 +117,19 @@ showcasing its capabilities in **information extraction**, **temporal and cross-
114117
- **Textual Memory**: For storing and retrieving unstructured or structured text knowledge.
115118
- **Activation Memory**: Caches key-value pairs (`KVCacheMemory`) to accelerate LLM inference and context reuse.
116119
- **Parametric Memory**: Stores model adaptation parameters (e.g., LoRA weights).
120+
- **Tool Memory** 🆕: Records Agent tool call trajectories and experiences to improve planning capabilities.
121+
- **📚 Knowledge Base System** 🆕: Build multi-dimensional knowledge bases with automatic document/URL parsing, splitting, and cross-project sharing capabilities.
122+
- **🔧 Memory Controllability** 🆕:
123+
- **Feedback Mechanism**: Use `add_feedback` API to correct, supplement, or replace existing memories with natural language.
124+
- **Precise Deletion**: Delete specific memories by User ID or Memory ID via API or MCP tools.
125+
- **👁️ Multi-Modal Support** 🆕: Support for image understanding and memory, including chart parsing in documents.
126+
- **⚡ Advanced Architecture**:
127+
- **DB Optimization**: Enhanced connection management and batch insertion for high-concurrency scenarios.
128+
- **Advanced Retrieval**: Custom tag and info field filtering with complex logical operations.
129+
- **Redis Streams Scheduler**: Multi-level queue architecture with intelligent orchestration for fair multi-tenant scheduling.
130+
- **Stream & Non-Stream Chat**: Ready-to-use streaming and non-streaming chat interfaces.
117131
- **🔌 Extensible**: Easily extend and customize memory modules, data sources, and LLM integrations.
132+
- **🏂 Lightweight Deployment** 🆕: Support for quick mode and complete mode deployment options.
118133

119134
## 🚀 Getting Started
120135

docker/.env.example

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ OLLAMA_API_BASE=http://localhost:11434 # required when backend=ollama
4747
MOS_RERANKER_BACKEND=http_bge # http_bge | http_bge_strategy | cosine_local
4848
MOS_RERANKER_URL=http://localhost:8001 # required when backend=http_bge*
4949
MOS_RERANKER_MODEL=bge-reranker-v2-m3 # siliconflow → use BAAI/bge-reranker-v2-m3
50-
MOS_RERANKER_HEADERS_EXTRA= # extra headers, JSON string
50+
MOS_RERANKER_HEADERS_EXTRA= # extra headers, JSON string, e.g. {"Authorization":"Bearer your_token"}
5151
MOS_RERANKER_STRATEGY=single_turn
5252
MOS_RERANK_SOURCE= # optional rerank scope, e.g., history/stream/custom
5353

@@ -93,6 +93,9 @@ NEO4J_DB_NAME=neo4j # required for shared-db mode
9393
MOS_NEO4J_SHARED_DB=false
9494
QDRANT_HOST=localhost
9595
QDRANT_PORT=6333
96+
# For Qdrant Cloud / remote endpoint (takes priority if set):
97+
QDRANT_URL=your_qdrant_url
98+
QDRANT_API_KEY=your_qdrant_key
9699
MILVUS_URI=http://localhost:19530 # required when ENABLE_PREFERENCE_MEMORY=true
97100
MILVUS_USER_NAME=root # same as above
98101
MILVUS_PASSWORD=12345678 # same as above
@@ -164,11 +167,6 @@ OSS_ACCESS_KEY_ID=
164167
OSS_ACCESS_KEY_SECRET=
165168
OSS_PUBLIC_BASE_URL=
166169

167-
## Logging / external sink
168-
CUSTOM_LOGGER_URL=
169-
CUSTOM_LOGGER_TOKEN=
170-
CUSTOM_LOGGER_WORKERS=2
171-
172170
## SDK / external client
173171
MEMOS_API_KEY=
174172
MEMOS_BASE_URL=https://memos.memtensor.cn/api/openmem/v1

docker/requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,7 @@ watchfiles==1.1.0
159159
websockets==15.0.1
160160
xlrd==2.0.2
161161
xlsxwriter==3.2.5
162+
prometheus-client==0.23.1
163+
pymilvus==2.5.12
164+
nltk==3.9.1
165+
rake-nltk==1.0.6

docs/openapi.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@
884884
"type": "string",
885885
"title": "Session Id",
886886
"description": "Session ID for the MOS. This is used to distinguish between different dialogue",
887-
"default": "41bb5e18-252d-4948-918c-07d82aa47086"
887+
"default": "8dcdbd62-c231-4678-a3ae-0946b7d9ce14"
888888
},
889889
"chat_model": {
890890
"$ref": "#/components/schemas/LLMConfigFactory",

docs/product-api-tests.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
## Product API smoke tests (local 0.0.0.0:8001)
2+
3+
Source: https://github.com/MemTensor/MemOS/issues/518
4+
5+
### Prerequisites
6+
- Service is running: `python -m uvicorn memos.api.server_api:app --host 0.0.0.0 --port 8001`
7+
- `.env` is configured for Redis, embeddings, and the vector DB (current test setup: Redis reachable, Qdrant Cloud connected).
8+
9+
### 1) /product/add
10+
- Purpose: Write a memory (sync/async).
11+
- Example request (sync):
12+
13+
```bash
14+
curl -s -X POST http://127.0.0.1:8001/product/add \
15+
-H 'Content-Type: application/json' \
16+
-d '{
17+
"user_id": "tester",
18+
"mem_cube_id": "default_cube",
19+
"memory_content": "Apple is a fruit rich in fiber.",
20+
"async_mode": "sync"
21+
}'
22+
```
23+
24+
- Observed result: `200`, message: "Memory added successfully", returns the written `memory_id` and related info.
25+
26+
### 2) /product/get_all
27+
- Purpose: List all memories for the user/type to confirm writes.
28+
- Example request:
29+
30+
```bash
31+
curl -s -X POST http://127.0.0.1:8001/product/get_all \
32+
-H 'Content-Type: application/json' \
33+
-d '{
34+
"user_id": "tester",
35+
"memory_type": "text_mem",
36+
"mem_cube_ids": ["default_cube"]
37+
}'
38+
```
39+
40+
- Observed result: `200`, shows the recently written apple memories (WorkingMemory/LongTermMemory/UserMemory present, `vector_sync=success`).
41+
42+
### 3) /product/search
43+
- Purpose: Vector search memories.
44+
- Example request:
45+
46+
```bash
47+
curl -s -X POST http://127.0.0.1:8001/product/search \
48+
-H 'Content-Type: application/json' \
49+
-d '{
50+
"query": "What fruit is rich in fiber?",
51+
"user_id": "tester",
52+
"mem_cube_id": "default_cube",
53+
"top_k": 5,
54+
"pref_top_k": 3,
55+
"include_preference": false
56+
}'
57+
```
58+
59+
- Observed result: previously returned 400 because payload indexes (e.g., `vector_sync`) were missing in Qdrant. Index creation is now automatic during Qdrant initialization (memory_type/status/vector_sync/user_name).
60+
- If results are empty or errors persist, verify indexes exist (auto-created on restart) or recreate/clean the collection.
61+
62+
### Notes / Next steps
63+
- `/product/add` and `/product/get_all` are healthy.
64+
- `/product/search` still returns empty results even with vectors present; likely related to search filters or vector retrieval.
65+
- Suggested follow-ups: inspect `SearchHandler` flow, filter conditions (user_id/session/cube_name), and vector DB search calls; capture logs or compare with direct `VecDBFactory.search` calls.

evaluation/scripts/locomo/locomo_eval.py

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import logging
55
import os
6+
import re
67
import time
78

89
import nltk
@@ -47,6 +48,29 @@ class LLMGrade(BaseModel):
4748
llm_reasoning: str = Field(description="Explain why the answer is correct or incorrect.")
4849

4950

51+
def extract_label_json(text: str) -> str | None:
52+
"""
53+
Extracts a JSON object of the form {"label": "VALUE"} from a given text string.
54+
This function is designed to handle cases where the LLM response contains
55+
natural language alongside a final JSON snippet, ensuring robust parsing.
56+
57+
Supports both single and double quotes around the label value.
58+
Ignores surrounding whitespace and formatting.
59+
60+
Returns:
61+
The full matching JSON string (e.g., '{"label": "CORRECT"}') if found.
62+
None if no valid label JSON is found.
63+
"""
64+
# Regex pattern to match: { "label": "value" } with optional whitespace
65+
# Matches both single and double quotes, allows spaces around keys and values
66+
pattern = r'\{\s*"label"\s*:\s*["\']([^"\']*)["\']\s*\}'
67+
match = re.search(pattern, text)
68+
if match:
69+
# Return the complete matched JSON string for safe json.loads()
70+
return match.group(0)
71+
return None
72+
73+
5074
async def locomo_grader(llm_client, question: str, gold_answer: str, response: str) -> bool:
5175
system_prompt = """
5276
You are an expert grader that determines if answers to questions match a gold standard answer
@@ -77,20 +101,23 @@ async def locomo_grader(llm_client, question: str, gold_answer: str, response: s
77101
78102
Just return the label CORRECT or WRONG in a json format with the key as "label".
79103
"""
80-
81-
response = await llm_client.chat.completions.create(
82-
model="gpt-4o-mini",
83-
messages=[
84-
{"role": "system", "content": system_prompt},
85-
{"role": "user", "content": accuracy_prompt},
86-
],
87-
temperature=0,
88-
)
89-
message_content = response.choices[0].message.content
90-
label = json.loads(message_content)["label"]
91-
parsed = LLMGrade(llm_judgment=label, llm_reasoning="")
92-
93-
return parsed.llm_judgment.strip().lower() == "correct"
104+
try:
105+
response = await llm_client.chat.completions.create(
106+
model=os.getenv("EVAL_MODEL", "gpt-4o-mini"),
107+
messages=[
108+
{"role": "system", "content": system_prompt},
109+
{"role": "user", "content": accuracy_prompt},
110+
],
111+
temperature=0,
112+
)
113+
message_content = response.choices[0].message.content
114+
message_content = extract_label_json(text=message_content)
115+
label = json.loads(message_content)["label"]
116+
parsed = LLMGrade(llm_judgment=label, llm_reasoning="")
117+
return parsed.llm_judgment.strip().lower() == "correct"
118+
except Exception as e:
119+
print(f"======== {e}, {response} ===========")
120+
exit()
94121

95122

96123
def calculate_rouge_scores(gold_answer, response):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# LongBench v2 evaluation scripts

0 commit comments

Comments
 (0)