Skip to content

Commit 60f41cf

Browse files
committed
feat: add dataset download
1 parent 2932abb commit 60f41cf

File tree

14 files changed

+208
-4
lines changed

14 files changed

+208
-4
lines changed

memory_benchmark/__init__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
from .launch import run_memory_benchmark
2+
from .env import CONFIG
3+
14
__author__ = "Memobase"
25
__version__ = "0.0.1.dev0"
36
__url__ = "https://github.com/memodb-io/memory-benchmark"
4-
5-
6-
print("Not ready")

memory_benchmark/datasets/base.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from pydantic import BaseModel
2+
3+
4+
class Message(BaseModel):
5+
role: str
6+
content: str
7+
alias: str | None = None
8+
id: str | None = None
9+
10+
11+
class Conversation(BaseModel):
12+
messages: list[Message]
13+
id: str | None = None
14+
15+
16+
class RemoteFile(BaseModel):
17+
url: str
18+
name: str
19+
hash: str

memory_benchmark/datasets/download.py

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import os
2+
import requests
3+
from rich.progress import track
4+
from hashlib import sha256
5+
from ..env import HOME_PATH, console
6+
from .base import RemoteFile
7+
8+
REMOTE_URLS = {
9+
"locomo": [
10+
RemoteFile(
11+
url="https://github.com/snap-research/locomo/raw/refs/heads/main/data/locomo10.json",
12+
name="locomo10.json",
13+
hash="79fa87e90f04081343b8c8debecb80a9a6842b76a7aa537dc9fdf651ea698ff4",
14+
)
15+
]
16+
}
17+
18+
19+
def exist_or_download(dataset: str):
20+
if check_local_dataset_exist(dataset):
21+
console.log(f"Dataset {dataset} already exists")
22+
else:
23+
download_from_github(dataset)
24+
25+
26+
def check_local_dataset_exist(dataset: str) -> bool:
27+
assert (
28+
dataset in REMOTE_URLS
29+
), f"Dataset {dataset} not found in {list(REMOTE_URLS.keys())}"
30+
31+
dataset_path = os.path.join(HOME_PATH, "datasets")
32+
if not os.path.exists(dataset_path):
33+
return False
34+
35+
local_path = os.path.join(dataset_path, dataset)
36+
if not os.path.exists(local_path):
37+
return False
38+
39+
for df in REMOTE_URLS[dataset]:
40+
local_file = os.path.join(local_path, df.name)
41+
if not os.path.exists(local_file):
42+
return False
43+
with open(local_file, "rb") as f:
44+
file_hash = sha256(f.read()).hexdigest()
45+
if file_hash != df.hash:
46+
return False
47+
return True
48+
49+
50+
def download_from_github(dataset: str):
51+
assert (
52+
dataset in REMOTE_URLS
53+
), f"Dataset {dataset} not found in {list(REMOTE_URLS.keys())}"
54+
55+
dataset_path = os.path.join(HOME_PATH, "datasets")
56+
if not os.path.exists(dataset_path):
57+
os.makedirs(dataset_path)
58+
59+
local_path = os.path.join(dataset_path, dataset)
60+
if not os.path.exists(local_path):
61+
os.makedirs(local_path)
62+
63+
# download the file
64+
console.log(f"Downloading {dataset} from GitHub")
65+
for df in track(
66+
REMOTE_URLS[dataset],
67+
description=f"Downloading {len(REMOTE_URLS[dataset])} files...",
68+
):
69+
local_file = os.path.join(local_path, df.name)
70+
response = requests.get(df.url)
71+
response.raise_for_status()
72+
73+
file_hash = sha256(response.content).hexdigest()
74+
assert (
75+
file_hash == df.hash
76+
), f"Hash of {df.name}, {dataset} does not match expected hash"
77+
78+
with open(local_file, "wb") as f:
79+
f.write(response.content)

memory_benchmark/datasets/locomo.py

Whitespace-only changes.

memory_benchmark/env.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import os
2+
from dataclasses import dataclass, field
3+
from rich.console import Console
4+
5+
6+
@dataclass
7+
class Config:
8+
llm_base_url: str | None = None
9+
llm_api_key: str | None = None
10+
llm_model: str = "gpt-4o-mini"
11+
12+
use_dataset: str = "locomo"
13+
use_method: str = "memobase"
14+
15+
extra_kwargs: dict = field(default_factory=dict)
16+
17+
18+
CONFIG = Config()
19+
20+
HOME_PATH = os.path.expanduser("~/.cache/memory_benchmark")
21+
if not os.path.exists(HOME_PATH):
22+
os.makedirs(HOME_PATH)
23+
24+
console = Console()

memory_benchmark/launch.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
async def run_memory_benchmark():
2+
pass

memory_benchmark/llms/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .openai import openai_complete
2+
3+
4+
llm_complete = openai_complete

memory_benchmark/llms/openai.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from openai import AsyncOpenAI
2+
from ..env import CONFIG
3+
from .types import LLMResult
4+
5+
_global_openai_async_client = None
6+
7+
8+
def get_openai_async_client_instance() -> AsyncOpenAI:
9+
global _global_openai_async_client
10+
if _global_openai_async_client is None:
11+
_global_openai_async_client = AsyncOpenAI(
12+
base_url=CONFIG.llm_base_url,
13+
api_key=CONFIG.llm_api_key,
14+
)
15+
return _global_openai_async_client
16+
17+
18+
async def openai_complete(
19+
model, prompt, system_prompt=None, history_messages=[], **kwargs
20+
) -> LLMResult:
21+
openai_async_client = get_openai_async_client_instance()
22+
messages = []
23+
if system_prompt:
24+
messages.append({"role": "system", "content": system_prompt})
25+
messages.extend(history_messages)
26+
messages.append({"role": "user", "content": prompt})
27+
28+
response = await openai_async_client.chat.completions.create(
29+
model=model, messages=messages, timeout=120, **kwargs
30+
)
31+
return LLMResult(
32+
content=response.choices[0].message.content,
33+
input_tokens=response.usage.prompt_tokens,
34+
output_tokens=response.usage.completion_tokens,
35+
)

memory_benchmark/llms/types.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from pydantic import BaseModel
2+
3+
4+
class LLMResult(BaseModel):
5+
content: str
6+
input_tokens: int
7+
output_tokens: int

memory_benchmark/methods/base.py

Whitespace-only changes.

memory_benchmark/utils.py

Whitespace-only changes.

readme.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<div align="center">
2+
<h1><code>memory-benchmark</code></h1>
3+
<p><strong>Run benchmark results for long-term memory backends</strong></p>
4+
<p>
5+
<img src="https://img.shields.io/badge/python->=3.11-blue">
6+
<a href="https://pypi.org/project/memory-benchmark/">
7+
<img src="https://img.shields.io/pypi/v/memory-benchmark.svg">
8+
</a>
9+
</div>
10+
11+
12+
13+
## Get Started
14+
15+
TODO
16+
17+
18+
19+
## Support Datasets
20+
21+
- [ ] [LOCOMO](https://snap-research.github.io/locomo/)
22+
23+
24+
25+
## Support Methods
26+
27+
- [ ] [Memobase](https://github.com/memodb-io/memobase)
28+
- [ ] [AgenticMemory](https://github.com/WujiangXu/AgenticMemory/tree/main)
29+
- [ ] [Mem0](https://github.com/mem0ai/mem0)
30+
- [ ] [MemGPT](https://github.com/letta-ai/letta)
31+
- [ ] [Zep](https://github.com/getzep/zep)

requirements.txt

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
rich
12
openai
3+
pydantic
4+
requests
25
memobase
36
transformers

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
url=vars2readme["__url__"],
2727
version=vars2readme["__version__"],
2828
author=vars2readme["__author__"],
29-
description="A unified benchmark framework for long-term memory",
29+
description="Run benchmark results for long-term memory backends",
3030
long_description=long_description,
3131
long_description_content_type="text/markdown",
3232
packages=find_packages(exclude=["tests"]),

0 commit comments

Comments
 (0)