Skip to content

Commit a4f32e0

Browse files
committed
Merge branch 'main' of https://github.com/staru09/memU into gemini_integration
2 parents a98bcb5 + bf44de7 commit a4f32e0

3 files changed

Lines changed: 110 additions & 11 deletions

File tree

.github/ISSUE_TEMPLATE/feature_request.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,28 @@ body:
1717
validations:
1818
required: true
1919

20+
- type: textarea
21+
id: motivation
22+
attributes:
23+
label: Motivation
24+
description: Why do we need this feature? What problem does it solve?
25+
placeholder: "Explain the use case and why this feature would be valuable."
26+
validations:
27+
required: true
28+
29+
- type: dropdown
30+
id: platform
31+
attributes:
32+
label: Platform
33+
description: Which platform(s) does this feature apply to?
34+
options:
35+
- Platform Independent
36+
- Linux
37+
- macOS
38+
- Windows
39+
validations:
40+
required: true
41+
2042
- type: dropdown
2143
id: priority
2244
attributes:

README.md

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ View detailed experimental data: [memU-experiment](https://github.com/NevaMind-A
415415
<div align="center">
416416

417417
<a href="https://github.com/TEN-framework/ten-framework"><img src="https://avatars.githubusercontent.com/u/113095513?s=200&v=4" alt="Ten" height="40" style="margin: 10px;"></a>
418-
<a href="GitHub - openagents-org/openagents: OpenAgents - AI Agent Networks for Open Collaboration"><img src="assets/partners/openagents.png" alt="OpenAgents" height="40" style="margin: 10px;"></a>
418+
<a href="https://openagents.org"><img src="assets/partners/openagents.png" alt="OpenAgents" height="40" style="margin: 10px;"></a>
419419
<a href="https://github.com/milvus-io/milvus"><img src="https://miro.medium.com/v2/resize:fit:2400/1*-VEGyAgcIBD62XtZWavy8w.png" alt="Milvus" height="40" style="margin: 10px;"></a>
420420
<a href="https://xroute.ai/"><img src="assets/partners/xroute.png" alt="xRoute" height="40" style="margin: 10px;"></a>
421421
<a href="https://jaaz.app/"><img src="assets/partners/jazz.png" alt="Jazz" height="40" style="margin: 10px;"></a>
@@ -427,6 +427,62 @@ View detailed experimental data: [memU-experiment](https://github.com/NevaMind-A
427427

428428
---
429429

430+
## 🤝 How to Contribute
431+
432+
We welcome contributions from the community! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated.
433+
434+
### Getting Started
435+
436+
To start contributing to MemU, you'll need to set up your development environment:
437+
438+
#### Prerequisites
439+
- Python 3.13+
440+
- [uv](https://github.com/astral-sh/uv) (Python package manager)
441+
- Git
442+
443+
#### Setup Development Environment
444+
445+
```bash
446+
# 1. Fork and clone the repository
447+
git clone https://github.com/YOUR_USERNAME/memU.git
448+
cd memU
449+
450+
# 2. Install development dependencies
451+
make install
452+
```
453+
454+
The `make install` command will:
455+
- Create a virtual environment using `uv`
456+
- Install all project dependencies
457+
- Set up pre-commit hooks for code quality checks
458+
459+
#### Running Quality Checks
460+
461+
Before submitting your contribution, ensure your code passes all quality checks:
462+
463+
```bash
464+
make check
465+
```
466+
467+
The `make check` command runs:
468+
- **Lock file verification**: Ensures `pyproject.toml` consistency
469+
- **Pre-commit hooks**: Lints code with Ruff, formats with Black
470+
- **Type checking**: Runs `mypy` for static type analysis
471+
- **Dependency analysis**: Uses `deptry` to find obsolete dependencies
472+
473+
### Contributing Guidelines
474+
475+
For detailed contribution guidelines, code standards, and development practices, please see [CONTRIBUTING.md](CONTRIBUTING.md).
476+
477+
**Quick tips:**
478+
- Create a new branch for each feature or bug fix
479+
- Write clear commit messages
480+
- Add tests for new functionality
481+
- Update documentation as needed
482+
- Run `make check` before pushing
483+
484+
---
485+
430486
## 📄 License
431487

432488
[Apache License 2.0](LICENSE.txt)
@@ -435,7 +491,7 @@ View detailed experimental data: [memU-experiment](https://github.com/NevaMind-A
435491

436492
## 🌍 Community
437493

438-
- **GitHub Issues**: [Report bugs & request features](NevaMind-AI/memU)
494+
- **GitHub Issues**: [Report bugs & request features](https://github.com/NevaMind-AI/memU/issues)
439495
- **Discord**: [Join the community](https://discord.com/invite/hQZntfGsbJ)
440496
- **X (Twitter)**: [Follow @memU_ai](https://x.com/memU_ai)
441497
- **Contact**: info@nevamind.ai

src/memu/database/inmemory/vector.py

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,37 @@ def cosine_topk(
1616
corpus: Iterable[tuple[str, list[float] | None]],
1717
k: int = 5,
1818
) -> list[tuple[str, float]]:
19-
q = np.array(query_vec, dtype=np.float32)
20-
scored: list[tuple[str, float]] = []
19+
# Filter out None vectors and collect valid entries
20+
ids: list[str] = []
21+
vecs: list[list[float]] = []
2122
for _id, vec in corpus:
22-
if vec is None:
23-
continue
24-
vec_list = cast(list[float], vec)
25-
v = np.array(vec_list, dtype=np.float32)
26-
scored.append((_id, _cosine(q, v)))
27-
scored.sort(key=lambda x: x[1], reverse=True)
28-
return scored[:k]
23+
if vec is not None:
24+
ids.append(_id)
25+
vecs.append(cast(list[float], vec))
26+
27+
if not vecs:
28+
return []
29+
30+
# Vectorized computation: stack all vectors into a matrix
31+
q = np.array(query_vec, dtype=np.float32)
32+
matrix = np.array(vecs, dtype=np.float32) # shape: (n, dim)
33+
34+
# Compute all cosine similarities at once
35+
q_norm = np.linalg.norm(q)
36+
vec_norms = np.linalg.norm(matrix, axis=1)
37+
scores = matrix @ q / (vec_norms * q_norm + 1e-9)
38+
39+
# Use argpartition for O(n) topk selection instead of O(n log n) sort
40+
n = len(scores)
41+
actual_k = min(k, n)
42+
if actual_k == n:
43+
topk_indices = np.argsort(scores)[::-1]
44+
else:
45+
# Get indices of top k elements (unordered), then sort only those
46+
topk_indices = np.argpartition(scores, -actual_k)[-actual_k:]
47+
topk_indices = topk_indices[np.argsort(scores[topk_indices])[::-1]]
48+
49+
return [(ids[i], float(scores[i])) for i in topk_indices]
2950

3051

3152
def query_cosine(query_vec: list[float], vecs: list[list[float]]) -> list[tuple[int, float]]:

0 commit comments

Comments
 (0)