Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7d33791
fix: add safe guard when parsing node memory
CaralHsi Sep 10, 2025
758cce5
feat: add filter as a parameter in tree-text searcher
CaralHsi Sep 10, 2025
f2d275b
feat: add filter for user and long-term memory
CaralHsi Sep 11, 2025
16ec612
feat: add filter in working memory
CaralHsi Sep 11, 2025
4765013
Merge branch 'dev' into feat/chat_bot_api
CaralHsi Sep 11, 2025
95c347d
add filter in task-parser
CaralHsi Sep 12, 2025
8db5752
feat: only mix-retrieve for vector-recall; TODO: mix reranker
CaralHsi Sep 12, 2025
b03d73e
feat: add 'session_id' as an optional parameter for product api
CaralHsi Sep 12, 2025
69e7829
feat: api 1.0 finish
CaralHsi Sep 15, 2025
30116c0
maintain: update gitignore
CaralHsi Sep 15, 2025
f0eff7e
maintain: update gitignore
CaralHsi Sep 15, 2025
5a1f26b
Merge branch 'feat/chat_bot_api' of github.com:CaralHsi/MemOSRealPubl…
CaralHsi Sep 15, 2025
5f7dac1
Merge branch 'dev' into feat/chat_bot_api
CaralHsi Sep 15, 2025
bd4f09d
feat: add 'type' in TextualMemory Sources
CaralHsi Sep 15, 2025
9c543bc
Merge branch 'feat/chat_bot_api' of github.com:CaralHsi/MemOSRealPubl…
CaralHsi Sep 15, 2025
ebec44b
feat: add annotation to item
CaralHsi Sep 15, 2025
ddb3524
fix: add session_id to product add
CaralHsi Sep 15, 2025
7dc386a
fix: test
CaralHsi Sep 15, 2025
15f6dc3
Merge branch 'test' into feat/chat_bot_api
CaralHsi Sep 15, 2025
c902ebc
feat: [WIP] add filter in reranker
CaralHsi Sep 16, 2025
58650c3
fix: conflict
CaralHsi Sep 16, 2025
4da163e
fix: bug in recall
CaralHsi Sep 16, 2025
6e84173
Merge branch 'test' into feat/chat_bot_api
CaralHsi Sep 16, 2025
ac16d5c
feat: finish search filter in reranker
CaralHsi Sep 16, 2025
febd094
fix: product router pydantic errir
CaralHsi Sep 16, 2025
0ca56a5
Merge branch 'feat/chat_bot_api' of github.com:CaralHsi/MemOSRealPubl…
CaralHsi Sep 16, 2025
12df87f
Merge branch 'test' into feat/chat_bot_api
CaralHsi Sep 16, 2025
319e75a
fix: internet search memory pydantic bug
CaralHsi Sep 16, 2025
a78f24f
fix: conflict
CaralHsi Sep 16, 2025
12126fb
fix: conflict
CaralHsi Sep 16, 2025
0420698
fix: internet search pydantic bug
CaralHsi Sep 16, 2025
c0263e2
fix: internet search pydantic bug
CaralHsi Sep 16, 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
Prev Previous commit
Next Next commit
feat: add filter for user and long-term memory
  • Loading branch information
CaralHsi committed Sep 11, 2025
commit f2d275b55bb4880ef22f2979fda78028a511d18b
12 changes: 12 additions & 0 deletions src/memos/graph_dbs/nebular.py
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,7 @@ def search_by_embedding(
scope: str | None = None,
status: str | None = None,
threshold: float | None = None,
search_filter: dict | None = None,
**kwargs,
) -> list[dict]:
"""
Expand All @@ -984,6 +985,8 @@ def search_by_embedding(
status (str, optional): Node status filter (e.g., 'active', 'archived').
If provided, restricts results to nodes with matching status.
threshold (float, optional): Minimum similarity score threshold (0 ~ 1).
search_filter (dict, optional): Additional metadata filters for search results.
Keys should match node properties, values are the expected values.

Returns:
list[dict]: A list of dicts with 'id' and 'score', ordered by similarity.
Expand All @@ -993,6 +996,7 @@ def search_by_embedding(
- If scope is provided, it restricts results to nodes with matching memory_type.
- If 'status' is provided, only nodes with the matching status will be returned.
- If threshold is provided, only results with score >= threshold will be returned.
- If search_filter is provided, additional WHERE clauses will be added for metadata filtering.
- Typical use case: restrict to 'status = activated' to avoid
matching archived or merged nodes.
"""
Expand All @@ -1012,6 +1016,14 @@ def search_by_embedding(
else:
where_clauses.append(f'n.user_name = "{self.config.user_name}"')

# Add search_filter conditions
if search_filter:
for key, value in search_filter.items():
if isinstance(value, str):
where_clauses.append(f'n.{key} = "{value}"')
else:
where_clauses.append(f"n.{key} = {value}")

where_clause = f"WHERE {' AND '.join(where_clauses)}" if where_clauses else ""

gql = f"""
Expand Down
19 changes: 18 additions & 1 deletion src/memos/graph_dbs/neo4j.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ def search_by_embedding(
scope: str | None = None,
status: str | None = None,
threshold: float | None = None,
search_filter: dict | None = None,
**kwargs,
) -> list[dict]:
"""
Expand All @@ -618,6 +619,8 @@ def search_by_embedding(
status (str, optional): Node status filter (e.g., 'active', 'archived').
If provided, restricts results to nodes with matching status.
threshold (float, optional): Minimum similarity score threshold (0 ~ 1).
search_filter (dict, optional): Additional metadata filters for search results.
Keys should match node properties, values are the expected values.

Returns:
list[dict]: A list of dicts with 'id' and 'score', ordered by similarity.
Expand All @@ -627,6 +630,7 @@ def search_by_embedding(
- If scope is provided, it restricts results to nodes with matching memory_type.
- If 'status' is provided, only nodes with the matching status will be returned.
- If threshold is provided, only results with score >= threshold will be returned.
- If search_filter is provided, additional WHERE clauses will be added for metadata filtering.
- Typical use case: restrict to 'status = activated' to avoid
matching archived or merged nodes.
"""
Expand All @@ -639,6 +643,12 @@ def search_by_embedding(
if not self.config.use_multi_db and self.config.user_name:
where_clauses.append("node.user_name = $user_name")

# Add search_filter conditions
if search_filter:
for key, _ in search_filter.items():
param_name = f"filter_{key}"
where_clauses.append(f"node.{key} = ${param_name}")

where_clause = ""
if where_clauses:
where_clause = "WHERE " + " AND ".join(where_clauses)
Expand All @@ -650,7 +660,8 @@ def search_by_embedding(
RETURN node.id AS id, score
"""

parameters = {"embedding": vector, "k": top_k, "scope": scope}
parameters = {"embedding": vector, "k": top_k}

if scope:
parameters["scope"] = scope
if status:
Expand All @@ -661,6 +672,12 @@ def search_by_embedding(
else:
parameters["user_name"] = self.config.user_name

# Add search_filter parameters
if search_filter:
for key, value in search_filter.items():
param_name = f"filter_{key}"
parameters[param_name] = value

with self.driver.session(database=self.db_name) as session:
result = session.run(query, parameters)
records = [{"id": record["id"], "score": record["score"]} for record in result]
Expand Down
7 changes: 7 additions & 0 deletions src/memos/graph_dbs/neo4j_community.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def search_by_embedding(
scope: str | None = None,
status: str | None = None,
threshold: float | None = None,
search_filter: dict | None = None,
**kwargs,
) -> list[dict]:
"""
Expand All @@ -140,6 +141,7 @@ def search_by_embedding(
scope (str, optional): Memory type filter (e.g., 'WorkingMemory', 'LongTermMemory').
status (str, optional): Node status filter (e.g., 'activated', 'archived').
threshold (float, optional): Minimum similarity score threshold (0 ~ 1).
search_filter (dict, optional): Additional metadata filters to apply.

Returns:
list[dict]: A list of dicts with 'id' and 'score', ordered by similarity.
Expand All @@ -149,6 +151,7 @@ def search_by_embedding(
- If 'scope' is provided, it restricts results to nodes with matching memory_type.
- If 'status' is provided, it further filters nodes by status.
- If 'threshold' is provided, only results with score >= threshold will be returned.
- If 'search_filter' is provided, it applies additional metadata-based filtering.
- The returned IDs can be used to fetch full node data from Neo4j if needed.
"""
# Build VecDB filter
Expand All @@ -163,6 +166,10 @@ def search_by_embedding(
else:
vec_filter["user_name"] = self.config.user_name

# Add search_filter conditions
if search_filter:
vec_filter.update(search_filter)

# Perform vector search
results = self.vec_db.search(query_vector=vector, top_k=top_k, filter=vec_filter)

Expand Down
1 change: 1 addition & 0 deletions src/memos/mem_os/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ def add(
doc_path: str | None = None,
mem_cube_id: str | None = None,
user_id: str | None = None,
**kwargs,
) -> None:
"""
Add textual memories to a MemCube.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,19 @@ def _vector_recall(
search_filter: dict | None = None,
) -> list[TextualMemoryItem]:
"""
TODO: use search filter if exists
# TODO: tackle with post-filter and pre-filter(5.18+) better.
Perform vector-based similarity retrieval using query embedding.
# TODO: tackle with post-filter and pre-filter(5.18+) better.
"""
all_matches = []

def search_single(vec):
return (
self.graph_store.search_by_embedding(
vector=vec, top_k=top_k, scope=memory_scope, cube_name=cube_name
vector=vec,
top_k=top_k,
scope=memory_scope,
cube_name=cube_name,
search_filter=search_filter,
)
or []
)
Expand Down