Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2fe6942
chore: bump version number to v0.2.0 (#66)
fridayL Jul 11, 2025
4f5b696
feat: one-click deployment with docker
tianxing02 Jul 21, 2025
7c6d58c
Merge remote-tracking branch 'origin/dev' into dev
tianxing02 Jul 21, 2025
faeea51
feat: one-click deployment with docker
tianxing02 Jul 21, 2025
8364606
Merge remote-tracking branch 'origin/dev' into dev
tianxing02 Jul 21, 2025
6942a7e
Merge remote-tracking branch 'origin/dev' into dev
tianxing02 Jul 21, 2025
a1158c9
feat: one-click deployment with docker
tianxing02 Jul 21, 2025
3964580
feat: one-click deployment with docker
tianxing02 Jul 21, 2025
b01decb
Merge branch 'MemTensor:dev' into dev
tianxing02 Jul 21, 2025
879a0e8
feat: one-click deployment with docker
tianxing02 Jul 21, 2025
e878ebf
Merge remote-tracking branch 'origin/dev' into dev
tianxing02 Jul 21, 2025
4a968f7
feat: one-click deployment with docker
tianxing02 Jul 21, 2025
4fd3573
feat: one-click deployment with docker
tianxing02 Jul 21, 2025
872312f
feat: one-click deployment with docker
tianxing02 Jul 21, 2025
b572f0f
chore: bump version number to v0.2.1 (#131)
fridayL Jul 21, 2025
b8e9bc4
Merge branch 'MemTensor:dev' into dev
tianxing02 Jul 22, 2025
b89d091
feat: one-click deployment with docker
tianxing02 Jul 22, 2025
2aa5db8
feat: one-click deployment with docker
tianxing02 Jul 22, 2025
19bdbfb
feat: docker settings modify
tianxing02 Jul 22, 2025
c3bf76f
Merge branch 'dev' into dev
CaralHsi Jul 23, 2025
1558921
Update tree_config.json
tianxing02 Jul 23, 2025
ed20468
Update simple_openapi_memos.py
tianxing02 Jul 23, 2025
b13d633
feat: docker settings modify
tianxing02 Jul 23, 2025
d109a80
Merge remote-tracking branch 'origin/dev' into dev
tianxing02 Jul 23, 2025
9c394d6
Merge branch 'MemTensor:main' into feat/nebular
tianxing02 Jul 23, 2025
10b7f54
feat: support nebular database
tianxing02 Jul 23, 2025
b70e063
Update Dockerfile
tianxing02 Jul 23, 2025
5829125
Update docker-compose.yml
tianxing02 Jul 23, 2025
26928a5
Update tree_config.json
tianxing02 Jul 23, 2025
61a5b49
Update simple_openapi_memos.py
tianxing02 Jul 23, 2025
262927e
Rename .env.example to docker/.env.example
tianxing02 Jul 23, 2025
46eb16f
feat: update requirement.txt
tianxing02 Jul 23, 2025
b7a5363
feat: update requirement.txt
tianxing02 Jul 23, 2025
fc3f7fa
feat: update requirement.txt
tianxing02 Jul 23, 2025
0353d10
Update nebular_example.py
tianxing02 Jul 23, 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
197 changes: 197 additions & 0 deletions examples/basic_modules/nebular_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
from datetime import datetime

from memos.configs.embedder import EmbedderConfigFactory
from memos.configs.graph_db import GraphDBConfigFactory
from memos.embedders.factory import EmbedderFactory
from memos.graph_dbs.factory import GraphStoreFactory
from memos.memories.textual.item import TextualMemoryItem, TreeNodeTextualMemoryMetadata


embedder_config = EmbedderConfigFactory.model_validate(
{
"backend": "universal_api",
"config": {
"provider": "openai",
"api_key": "sk-xxxxxxxx",
"model_name_or_path": "text-embedding-3-large",
"base_url": "http://xxx.xxx.xxx.xxx:xxxx/v1",
},
}
)
embedder = EmbedderFactory.from_config(embedder_config)


def embed_memory_item(memory: str) -> list[float]:
return embedder.embed([memory])[0]


def example_multi_db(db_name: str = "paper"):
# Step 1: Build factory config
config = GraphDBConfigFactory(
backend="nebular",
config={
"hosts": ["xxx.xx.xxx.xx:xxxx", "xxx.xx.xxx.xx:xxxx", "xxx.xx.xxx.xx:xxxx"],
"user_name": "root",
"password": "xxxxxxxx",
"space": db_name,
"auto_create": True,
"embedding_dimension": 3072,
"use_multi_db": True,
},
)

# Step 2: Instantiate the graph store
graph = GraphStoreFactory.from_config(config)
graph.clear()

# Step 3: Create topic node
topic = TextualMemoryItem(
memory="This research addresses long-term multi-UAV navigation for energy-efficient communication coverage.",
metadata=TreeNodeTextualMemoryMetadata(
memory_type="LongTermMemory",
key="Multi-UAV Long-Term Coverage",
hierarchy_level="topic",
type="fact",
memory_time="2024-01-01",
source="file",
sources=["paper://multi-uav-coverage/intro"],
status="activated",
confidence=95.0,
tags=["UAV", "coverage", "multi-agent"],
entities=["UAV", "coverage", "navigation"],
visibility="public",
updated_at=datetime.now().isoformat(),
embedding=embed_memory_item(
"This research addresses long-term "
"multi-UAV navigation for "
"energy-efficient communication "
"coverage."
),
),
)

graph.add_node(
id=topic.id, memory=topic.memory, metadata=topic.metadata.model_dump(exclude_none=True)
)


def example_shared_db(db_name: str = "shared-traval-group"):
"""
Example: Single(Shared)-DB multi-tenant (logical isolation)
Multiple users' data in the same Neo4j DB with user_name as a tag.
"""
# users
user_list = ["travel_member_alice", "travel_member_bob"]

for user_name in user_list:
# Step 1: Build factory config
config = GraphDBConfigFactory(
backend="nebular",
config={
"hosts": ["xxx.xx.xxx.xx:xxxx", "xxx.xx.xxx.xx:xxxx", "xxx.xx.xxx.xx:xxxx"],
"password": "xxxxxxxx",
"space": db_name,
"user_name": "root",
"auto_create": True,
"embedding_dimension": 3072,
"use_multi_db": False,
},
)

# Step 2: Instantiate graph store
graph = GraphStoreFactory.from_config(config)
print(f"\n[INFO] Working in shared DB: {db_name}, for user: {user_name}")
graph.clear()

# Step 3: Create topic node
topic = TextualMemoryItem(
memory="This research addresses long-term multi-UAV navigation for energy-efficient communication coverage.",
metadata=TreeNodeTextualMemoryMetadata(
memory_type="LongTermMemory",
key="Multi-UAV Long-Term Coverage",
hierarchy_level="topic",
type="fact",
memory_time="2024-01-01",
source="file",
sources=["paper://multi-uav-coverage/intro"],
status="activated",
confidence=95.0,
tags=["UAV", "coverage", "multi-agent"],
entities=["UAV", "coverage", "navigation"],
visibility="public",
updated_at=datetime.now().isoformat(),
embedding=embed_memory_item(
"This research addresses long-term "
"multi-UAV navigation for "
"energy-efficient communication "
"coverage."
),
),
)

graph.add_node(
id=topic.id, memory=topic.memory, metadata=topic.metadata.model_dump(exclude_none=True)
)

# Step 4: Add a concept for each user
concept = TextualMemoryItem(
memory=f"Itinerary plan for {user_name}",
metadata=TreeNodeTextualMemoryMetadata(
memory_type="LongTermMemory",
key="Multi-UAV Long-Term Coverage",
hierarchy_level="concept",
type="fact",
memory_time="2024-01-01",
source="file",
sources=["paper://multi-uav-coverage/intro"],
status="activated",
confidence=95.0,
tags=["UAV", "coverage", "multi-agent"],
entities=["UAV", "coverage", "navigation"],
visibility="public",
updated_at=datetime.now().isoformat(),
embedding=embed_memory_item(f"Itinerary plan for {user_name}"),
),
)

graph.add_node(
id=concept.id,
memory=concept.memory,
metadata=concept.metadata.model_dump(exclude_none=True),
)

# Link concept to topic
graph.add_edge(source_id=concept.id, target_id=topic.id, type="RELATE_TO")

print(f"[INFO] Added nodes for {user_name}")

# Step 5: Query and print ALL for verification
print("\n=== Export entire DB (for verification, includes ALL users) ===")
graph = GraphStoreFactory.from_config(config)
all_graph_data = graph.export_graph()
print(all_graph_data)

# Step 6: Search for alice's data only
print("\n=== Search for travel_member_alice ===")
config_alice = GraphDBConfigFactory(
backend="nebular",
config={
"hosts": ["xxx.xx.xxx.xx:xxxx", "xxx.xx.xxx.xx:xxxx", "xxx.xx.xxx.xx:xxxx"],
"password": "xxxxxxxx",
"space": db_name,
"user_name": "root",
"embedding_dimension": 3072,
},
)
graph_alice = GraphStoreFactory.from_config(config_alice)
nodes = graph_alice.search_by_embedding(vector=embed_memory_item("travel itinerary"), top_k=1)
for node in nodes:
print(graph_alice.get_node(node["id"]))


if __name__ == "__main__":
print("\n=== Example: Multi-DB ===")
example_multi_db(db_name="paper")

print("\n=== Example: Single-DB ===")
example_shared_db(db_name="shared_traval_group")
52 changes: 51 additions & 1 deletion src/memos/configs/graph_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Neo4jGraphDBConfig(BaseGraphDBConfig):
),
)

embedding_dimension: int = Field(default=768, description="Dimension of vector embedding")
embedding_dimension: int = Field(default=3072, description="Dimension of vector embedding")

@model_validator(mode="after")
def validate_config(self):
Expand Down Expand Up @@ -103,13 +103,63 @@ def validate_community(self):
return self


class NebulaGraphDBConfig(BaseConfig):
"""
NebulaGraph-specific configuration.

Key concepts:
- `space`: Equivalent to a database or namespace. All tag/edge/schema live within a space.
- `user_name`: Used for logical tenant isolation if needed.
- `auto_create`: Whether to automatically create the target space if it does not exist.

Example:
---
hosts = ["127.0.0.1:9669"]
user = "root"
password = "nebula"
space = "shared_graph"
user_name = "alice"
"""

password: str
hosts: list[str] = Field(..., description="List of host:port strings for NebulaGraph servers")
space: str = Field(
..., description="The name of the target NebulaGraph space (like a database)"
)
user_name: str | None = Field(
default=None,
description="Logical user or tenant ID for data isolation (optional, used in metadata tagging)",
)
auto_create: bool = Field(
default=False,
description="Whether to auto-create the space if it does not exist",
)
use_multi_db: bool = Field(
default=True,
description=(
"If True: use Neo4j's multi-database feature for physical isolation; "
"each user typically gets a separate database. "
"If False: use a single shared database with logical isolation by user_name."
),
)
embedding_dimension: int = Field(default=3072, description="Dimension of vector embedding")

@model_validator(mode="after")
def validate_config(self):
"""Validate config."""
if not self.space:
raise ValueError("`space` must be provided")
return self


class GraphDBConfigFactory(BaseModel):
backend: str = Field(..., description="Backend for graph database")
config: dict[str, Any] = Field(..., description="Configuration for the graph database backend")

backend_to_class: ClassVar[dict[str, Any]] = {
"neo4j": Neo4jGraphDBConfig,
"neo4j-community": Neo4jCommunityGraphDBConfig,
"nebular": NebulaGraphDBConfig,
}

@field_validator("backend")
Expand Down
2 changes: 2 additions & 0 deletions src/memos/graph_dbs/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from memos.configs.graph_db import GraphDBConfigFactory
from memos.graph_dbs.base import BaseGraphDB
from memos.graph_dbs.nebular import NebulaGraphDB
from memos.graph_dbs.neo4j import Neo4jGraphDB
from memos.graph_dbs.neo4j_community import Neo4jCommunityGraphDB

Expand All @@ -12,6 +13,7 @@ class GraphStoreFactory(BaseGraphDB):
backend_to_class: ClassVar[dict[str, Any]] = {
"neo4j": Neo4jGraphDB,
"neo4j-community": Neo4jCommunityGraphDB,
"nebular": NebulaGraphDB,
}

@classmethod
Expand Down
Loading
Loading