Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
70373f9
fix playground bug, internet search judge
Dec 4, 2025
d181339
Merge branch 'dev' into feat/fix_palyground_bug
Dec 4, 2025
11cf00a
fix playground internet bug
Dec 4, 2025
6b10ce1
merge dev
Dec 4, 2025
c861f61
modify delete mem
Dec 4, 2025
e638039
modify tool resp bug in multi cube
Dec 4, 2025
dcd3d50
Merge branch 'dev' into feat/fix_palyground_bug
Dec 4, 2025
0c0eff8
Merge branch 'dev' into feat/fix_palyground_bug
Dec 5, 2025
8765dc4
fix bug in playground chat handle and search inter
Dec 5, 2025
1a335db
modify prompt
Dec 5, 2025
18320ff
fix bug in playground
Dec 6, 2025
666b897
fix bug playfround
Dec 6, 2025
275b9b6
Merge branch 'dev' into feat/fix_palyground_bug
Dec 7, 2025
0d22512
fix bug
Dec 7, 2025
d38f55f
Merge branch 'dev' into feat/fix_palyground_bug
Dec 7, 2025
a9eb1f6
fix code
Dec 7, 2025
94ad709
Merge branch 'dev' into feat/fix_palyground_bug
Dec 7, 2025
723a14f
fix model bug in playground
Dec 7, 2025
6f06a23
Merge branch 'dev' into feat/fix_palyground_bug
Dec 7, 2025
a300670
Merge branch 'dev' into feat/fix_palyground_bug
Dec 8, 2025
7ee13b1
Merge branch 'dev' into feat/fix_palyground_bug
Dec 8, 2025
5ab6e92
modify plan b
Dec 8, 2025
1bb0bcd
llm param modify
Dec 8, 2025
1b607e7
Merge branch 'dev' into feat/fix_palyground_bug
Dec 8, 2025
f5bc426
add logger in playground
Dec 8, 2025
a9fa309
modify code
Dec 9, 2025
d2efa24
Merge branch 'dev' into feat/fix_palyground_bug
Dec 9, 2025
9ebfbe1
Merge branch 'dev' into feat/fix_palyground_bug
fridayL Dec 9, 2025
4c055d0
fix bug
Dec 9, 2025
27b4fc4
modify code
Dec 9, 2025
cefeefb
modify code
Dec 9, 2025
7e05fa7
fix bug
Dec 9, 2025
a4f66b1
Merge branch 'dev' into feat/fix_palyground_bug
Dec 9, 2025
9b47647
Merge branch 'dev' into feat/fix_palyground_bug
Dec 9, 2025
05da172
fix search bug in plarground
Dec 9, 2025
e410ec2
fixx bug
Dec 9, 2025
0324588
move schadualr to back
Dec 9, 2025
a834028
Merge branch 'dev' into feat/fix_palyground_bug
Dec 9, 2025
4084954
modify pref location
Dec 9, 2025
de5e372
Merge branch 'dev' into feat/fix_palyground_bug
Dec 9, 2025
87861ab
Merge branch 'dev' into feat/fix_palyground_bug
Dec 9, 2025
8b547b8
modify fast net search
Dec 9, 2025
c915867
Merge branch 'dev' into feat/fix_palyground_bug
Dec 9, 2025
2f238fd
Merge branch 'dev' into feat/fix_palyground_bug
Dec 9, 2025
4543332
add tags and new package
Dec 10, 2025
c51ef0d
merge dev
Dec 10, 2025
033e8bd
modify prompt fix bug
Dec 10, 2025
e300112
Merge branch 'dev' into feat/fix_palyground_bug
Dec 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docker/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,5 @@ xlrd==2.0.2
xlsxwriter==3.2.5
prometheus-client==0.23.1
pymilvus==2.5.12
nltk==3.9.1
rake-nltk==1.0.6
24 changes: 20 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ all = [
"sentence-transformers (>=4.1.0,<5.0.0)",
"qdrant-client (>=1.14.2,<2.0.0)",
"volcengine-python-sdk (>=4.0.4,<5.0.0)",
"nltk (>=3.9.1,<4.0.0)",
"rake-nltk (>=1.0.6,<1.1.0)",

# Uncategorized dependencies
]
Expand Down
24 changes: 12 additions & 12 deletions src/memos/api/handlers/chat_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,16 +395,6 @@ def generate_chat_response() -> Generator[str, None, None]:
[chat_req.mem_cube_id] if chat_req.mem_cube_id else [chat_req.user_id]
)

# for playground, add the query to memory without response
self._start_add_to_memory(
user_id=chat_req.user_id,
writable_cube_ids=writable_cube_ids,
session_id=chat_req.session_id or "default_session",
query=chat_req.query,
full_response=None,
async_mode="sync",
)

# ====== first search text mem with parse goal ======
search_req = APISearchPlaygroundRequest(
query=chat_req.query,
Expand Down Expand Up @@ -450,7 +440,7 @@ def generate_chat_response() -> Generator[str, None, None]:
pref_list = search_response.data.get("pref_mem") or []
pref_memories = pref_list[0].get("memories", []) if pref_list else []
pref_md_string = self._build_pref_md_string_for_playground(pref_memories)
yield f"data: {json.dumps({'type': 'pref_md_string', 'data': pref_md_string})}\n\n"
yield f"data: {json.dumps({'type': 'pref_md_string', 'data': pref_md_string}, ensure_ascii=False)}\n\n"

# Use first readable cube ID for scheduler (backward compatibility)
scheduler_cube_id = (
Expand Down Expand Up @@ -531,6 +521,16 @@ def generate_chat_response() -> Generator[str, None, None]:
)
yield f"data: {json.dumps({'type': 'reference', 'data': reference})}\n\n"

# for playground, add the query to memory without response
self._start_add_to_memory(
user_id=chat_req.user_id,
writable_cube_ids=writable_cube_ids,
session_id=chat_req.session_id or "default_session",
query=chat_req.query,
full_response=None,
async_mode="sync",
)

# Step 2: Build system prompt with memories
system_prompt = self._build_enhance_system_prompt(
filtered_memories, pref_string
Expand Down Expand Up @@ -794,7 +794,7 @@ def _build_enhance_system_prompt(
sys_body
+ "\n\n# Memories\n## PersonalMemory (ordered)\n"
+ mem_block_p
+ "\n## OuterMemory (ordered)\n"
+ "\n## OuterMemory (from Internet Search, ordered)\n"
+ mem_block_o
+ f"\n\n{pref_string}"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import requests

from memos.context.context import ContextThreadPoolExecutor
from memos.dependency import require_python_package
from memos.embedders.factory import OllamaEmbedder
from memos.log import get_logger
from memos.mem_reader.base import BaseMemReader
from memos.mem_reader.read_multi_modal import detect_lang
from memos.memories.textual.item import (
SearchedTreeNodeTextualMemoryMetadata,
SourceMessage,
Expand Down Expand Up @@ -121,6 +123,21 @@ def _post(self, url: str, body: dict) -> list[dict]:
class BochaAISearchRetriever:
"""BochaAI retriever that converts search results into TextualMemoryItem objects"""

@require_python_package(
import_name="rake_nltk",
install_command="pip install rake_nltk",
install_link="https://pypi.org/project/rake-nltk/",
)
@require_python_package(
import_name="nltk",
install_command="pip install nltk",
install_link="https://www.nltk.org/install.html",
)
@require_python_package(
import_name="jieba",
install_command="pip install jieba",
install_link="https://github.com/fxsjy/jieba",
)
def __init__(
self,
access_key: str,
Expand All @@ -137,9 +154,25 @@ def __init__(
reader: MemReader instance for processing internet content
max_results: Maximum number of search results to retrieve
"""
import nltk

try:
nltk.download("averaged_perceptron_tagger_eng")
except Exception as err:
raise Exception("Failed to download nltk averaged_perceptron_tagger_eng") from err
try:
nltk.download("stopwords")
except Exception as err:
raise Exception("Failed to download nltk stopwords") from err

from jieba.analyse import TextRank
from rake_nltk import Rake

self.bocha_api = BochaAISearchAPI(access_key, max_results=max_results)
self.embedder = embedder
self.reader = reader
self.en_fast_keywords_extractor = Rake()
self.zh_fast_keywords_extractor = TextRank()

def retrieve_from_internet(
self, query: str, top_k: int = 10, parsed_goal=None, info=None, mode="fast"
Expand Down Expand Up @@ -224,6 +257,13 @@ def _process_result(
info_ = info.copy()
user_id = info_.pop("user_id", "")
session_id = info_.pop("session_id", "")
lang = detect_lang(summary)
tags = (
self.zh_fast_keywords_extractor.textrank(summary)[:3]
if lang == "zh"
else self.en_fast_keywords_extractor.extract_keywords_from_text(summary)[:3]
)

return [
TextualMemoryItem(
memory=(
Expand All @@ -244,6 +284,7 @@ def _process_result(
background="",
confidence=0.99,
usage=[],
tags=tags,
embedding=self.embedder.embed([content])[0],
internet_info={
"title": title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
1. Keys: the high-level keywords directly relevant to the user’s task.
2. Tags: thematic tags to help categorize and retrieve related memories.
3. Goal Type: retrieval | qa | generation
4. Rephrased instruction: Give a rephrased task instruction based on the former conversation to make it less confusing to look alone. Make full use of information related to the query. If you think the task instruction is easy enough to understand, or there is no former conversation, set "rephrased_instruction" to an empty string.
4. Rephrased instruction: Give a rephrased task instruction based on the former conversation to make it less confusing to look alone. Make full use of information related to the query, including user's personal information. If you think the task instruction is easy enough to understand, or there is no former conversation, set "rephrased_instruction" to an empty string.
5. Need for internet search: If the user's task instruction only involves objective facts or can be completed without introducing external knowledge, set "internet_search" to False. Otherwise, set it to True.
6. Memories: Provide 2–5 short semantic expansions or rephrasings of the rephrased/original user task instruction. These are used for improved embedding search coverage. Each should be clear, concise, and meaningful for retrieval.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ def _process_result(
source="web",
sources=[SourceMessage(type="web", url=url)] if url else [],
visibility="public",
tags=self._extract_tags(title, content, summary),
info=info_,
background="",
confidence=0.99,
Expand Down
5 changes: 3 additions & 2 deletions src/memos/templates/mos_prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
MEMOS_PRODUCT_BASE_PROMPT = """
# System
- Role: You are MemOS🧚, nickname Little M(小忆🧚) — an advanced Memory Operating System assistant by 记忆张量(MemTensor Technology Co., Ltd.), a Shanghai-based AI research company advised by an academician of the Chinese Academy of Sciences.
- Date: {date}

- Mission & Values: Uphold MemTensor’s vision of "low cost, low hallucination, high generalization, exploring AI development paths aligned with China’s national context and driving the adoption of trustworthy AI technologies. MemOS’s mission is to give large language models (LLMs) and autonomous agents **human-like long-term memory**, turning memory from a black-box inside model weights into a **manageable, schedulable, and auditable** core resource.

Expand Down Expand Up @@ -105,12 +104,14 @@
- When using facts from memories, add citations at the END of the sentence with `[i:memId]`.
- `i` is the order in the "Memories" section below (starting at 1). `memId` is the given short memory ID.
- Multiple citations must be concatenated directly, e.g., `[1:sed23s], [
2:1k3sdg], [3:ghi789]`. Do NOT use commas inside brackets.
2:1k3sdg], [3:ghi789]`. Do NOT use commas inside brackets. Do not use wrong format like `[def456]`.
- Cite only relevant memories; keep citations minimal but sufficient.
- Do not use a connected format like [1:abc123,2:def456].
- Brackets MUST be English half-width square brackets `[]`, NEVER use Chinese full-width brackets `【】` or any other symbols.
- **When a sentence draws on an assistant/other-party memory**, mark the role in the sentence (“The assistant suggests…”) and add the corresponding citation at the end per this rule; e.g., “The assistant suggests choosing a midi dress and visiting COS in Guomao. [1:abc123]”

# Current Date: {date}

# Style
- Tone: {tone}; Verbosity: {verbosity}.
- Be direct, well-structured, and conversational. Avoid fluff. Use short lists when helpful.
Expand Down