Skip to content

Commit 3f1911e

Browse files
authored
feat: support use ollama as embedding provider(#138) (#139)
* support use ollama as embedding provider * add ollama embedding example config and update readme
1 parent 936f453 commit 3f1911e

File tree

6 files changed

+61
-3
lines changed

6 files changed

+61
-3
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
llm_api_key: XXX
2+
llm_base_url: https://api.openai.com/v1/
3+
best_llm_model: gpt-4o
4+
5+
embedding_provider: ollama
6+
embedding_api_key: ollama
7+
embedding_base_url: "http://127.0.0.1:11434/" # WITHOUT "v1" at the end
8+
embedding_model: "qwen3-embedding:4b-q4_K_M"
9+
embedding_dim: 2560
10+
11+
language: en

src/server/api/memobase_server/env.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class Config:
102102
summary_llm_model: str = None
103103

104104
enable_event_embedding: bool = True
105-
embedding_provider: Literal["openai", "jina"] = "openai"
105+
embedding_provider: Literal["openai", "jina", "ollama"] = "openai"
106106
embedding_api_key: str = None
107107
embedding_base_url: str = None
108108
embedding_dim: int = 1536

src/server/api/memobase_server/llms/embeddings/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
from .jina_embedding import jina_embedding
1010
from .openai_embedding import openai_embedding
1111
from .lmstudio_embedding import lmstudio_embedding
12+
from .ollama_embedding import ollama_embedding
1213
from ...telemetry import telemetry_manager, HistogramMetricName, CounterMetricName
1314
from ...utils import get_encoded_tokens
1415

15-
FACTORIES = {"openai": openai_embedding, "jina": jina_embedding, "lmstudio": lmstudio_embedding}
16+
FACTORIES = {"openai": openai_embedding, "jina": jina_embedding, "lmstudio": lmstudio_embedding, "ollama": ollama_embedding}
1617
assert (
1718
CONFIG.embedding_provider in FACTORIES
1819
), f"Unsupported embedding provider: {CONFIG.embedding_provider}"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import numpy as np
2+
from typing import Literal
3+
from ...errors import ExternalAPIError
4+
from ...env import CONFIG, LOG
5+
from .utils import get_ollama_async_client_instance
6+
7+
OLLAMA_TASK = {
8+
"query": "retrieval.query",
9+
"document": "retrieval.passage",
10+
}
11+
12+
13+
async def ollama_embedding(
14+
model: str, texts: list[str], phase: Literal["query", "document"] = "document"
15+
) -> np.ndarray:
16+
openai_async_client = get_ollama_async_client_instance()
17+
response = await openai_async_client.post(
18+
"/api/embed",
19+
json={
20+
"model": model,
21+
"input": texts,
22+
# "task": OLLAMA_TASK[phase],
23+
"truncate": True,
24+
"dimensions": CONFIG.embedding_dim,
25+
},
26+
timeout=20,
27+
)
28+
if response.status_code != 200:
29+
raise ExternalAPIError(f"Failed to embed texts: {response.text}")
30+
data = response.json()
31+
LOG.info(
32+
f"Ollama embedding, {model}, {data['load_duration']}/{data['total_duration']}"
33+
)
34+
return np.array(data["embeddings"])

src/server/api/memobase_server/llms/embeddings/utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
_global_openai_async_client = None
66
_global_jina_async_client = None
77
_global_lmstudio_async_client = None
8+
_global_ollama_async_client = None
89

910

1011
def get_openai_async_client_instance() -> AsyncOpenAI:
@@ -34,3 +35,13 @@ def get_lmstudio_async_client_instance() -> AsyncClient:
3435
headers={"Authorization": f"Bearer {CONFIG.embedding_api_key}"},
3536
)
3637
return _global_lmstudio_async_client
38+
39+
def get_ollama_async_client_instance() -> AsyncClient:
40+
global _global_ollama_async_client
41+
if _global_ollama_async_client is None:
42+
_global_ollama_async_client = AsyncClient(
43+
base_url=CONFIG.embedding_base_url,
44+
headers={"Authorization": f"Bearer {CONFIG.embedding_api_key}"},
45+
)
46+
return _global_ollama_async_client
47+

src/server/readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ Memobase uses a single `config.yaml` to initialize the server. It contains the
2929
By default, Memobase enables user profile and event memory with filter ability. That means running a Memobase server requires you to have below things:
3030

3131
- **LLM API**: You must fill the OpenAI API Key in `llm_api_key` of `config.yaml`.Or you can change `llm_base_url` to any OpenAI-SDK-Compatible service(via [vllm](https://github.com/vllm-project/vllm), [Ollama](../../assets/tutorials/ollama+memobase/readme.md),...). Alternatively, you can set `llm_api_key` and `llm_base_url` using environment variables `MEMOBASE_LLM_API_KEY` and `MEMOBASE_LLM_BASE_URL`
32-
- **Embedding API**: Memobase supports OpenAI-Compatible SDK and [Jina Embedding](https://jina.ai/models/jina-embeddings-v3/). Memobase uses embedding API to retrieve related user events. If you don't have a embedding API, you can set `enable_event_embedding: false` in `config.yaml`
32+
- **Embedding API**: Memobase supports OpenAI-Compatible SDK, [Jina Embedding](https://jina.ai/models/jina-embeddings-v3/) and [Ollama Embedding](https://docs.ollama.com/api#generate-embeddings). Memobase uses embedding API to retrieve related user events. If you don't have a embedding API, you can set `enable_event_embedding: false` in `config.yaml`
3333

3434
We have some example `config.yaml` in `examplel_config`:
3535

3636
- [`profile_for_assistant`](./api/example_config/profile_for_education), [`profile_for_education`](./api/example_config/profile_for_education), [`profile_for_companion`](./api/example_config/profile_for_companion) are three similar configs in term of structure, but for different user cases.
3737
- [`event_tag`](./api/example_config/event_tag) is a feature to tracking temporal attributes of users. [doc](https://docs.memobase.io/features/event/event_tag)
3838
- [`only_strict_profile`](./api/example_config/only_strict_profile): disable all other features, only collect the profiles you design.
3939
- [`jina_embedding`](./api/example_config/jina_embedding) uses Jina exmbedding for event search.
40+
- [`ollama_embedding`](./api/example_config/ollama_embedding) uses Ollama exmbedding for event search.
4041

4142

4243

0 commit comments

Comments
 (0)