diff --git a/docs/components/vectordbs/dbs/qdrant.mdx b/docs/components/vectordbs/dbs/qdrant.mdx index 8f6d00ac94..f9df942513 100644 --- a/docs/components/vectordbs/dbs/qdrant.mdx +++ b/docs/components/vectordbs/dbs/qdrant.mdx @@ -18,8 +18,7 @@ config = { "provider": "qdrant", "config": { "collection_name": "test", - "host": "localhost", - "port": 6333, + "url": "http://localhost:6333", } } } @@ -90,4 +89,11 @@ Let's see the available parameters for the `qdrant` config: | `apiKey` | API key for the Qdrant server | `None` | | `onDisk` | For enabling persistent storage | `False` | - \ No newline at end of file + + + + For a self-hosted Qdrant server exposed over plain HTTP with API key authentication, + use `url: "http://..."` (or set `QDRANT_URL`) together with `api_key` (or + `QDRANT_API_KEY`). Avoid using `host` + `port` + `api_key` for this case because + the Python `qdrant-client` defaults to HTTPS when an API key is provided. + diff --git a/docs/open-source/configuration.mdx b/docs/open-source/configuration.mdx index 5812bfcedb..c46b50c7b1 100644 --- a/docs/open-source/configuration.mdx +++ b/docs/open-source/configuration.mdx @@ -63,7 +63,7 @@ from mem0 import Memory config = { "vector_store": { "provider": "qdrant", - "config": {"host": "localhost", "port": 6333}, + "config": {"url": "http://localhost:6333"}, }, "llm": { "provider": "openai", @@ -98,8 +98,7 @@ export COHERE_API_KEY="..." vector_store: provider: qdrant config: - host: localhost - port: 6333 + url: http://localhost:6333 llm: provider: azure_openai @@ -133,6 +132,12 @@ memory = Memory.from_config_file("config.yaml") Run `memory.add(["Remember my favorite cafe in Tokyo."], user_id="alex")` and then `memory.search("favorite cafe", filters={"user_id": "alex"})`. You should see the Qdrant collection populate and the reranker mark the memory as a top hit. + + If your self-hosted Qdrant server uses plain HTTP with API key authentication, set + `url: "http://..."` in the Qdrant config or export `QDRANT_URL`. The Python + `qdrant-client` treats `host` + `port` + `api_key` as HTTPS by default. + + ## Tune component settings diff --git a/mem0/configs/vector_stores/qdrant.py b/mem0/configs/vector_stores/qdrant.py index a610883884..dfd3ce9417 100644 --- a/mem0/configs/vector_stores/qdrant.py +++ b/mem0/configs/vector_stores/qdrant.py @@ -1,3 +1,4 @@ +import os from typing import Any, ClassVar, Dict, Optional from pydantic import BaseModel, ConfigDict, Field, model_validator @@ -21,13 +22,26 @@ class QdrantConfig(BaseModel): @model_validator(mode="before") @classmethod def check_host_port_or_path(cls, values: Dict[str, Any]) -> Dict[str, Any]: - host, port, path, url, api_key = ( + host, port, path, url, api_key, client = ( values.get("host"), values.get("port"), values.get("path"), values.get("url"), values.get("api_key"), + values.get("client"), ) + + if not client and not url and not (host and port) and not path: + env_url = os.environ.get("QDRANT_URL") + if env_url: + values["url"] = env_url + url = env_url + if not api_key: + env_api_key = os.environ.get("QDRANT_API_KEY") + if env_api_key: + values["api_key"] = env_api_key + api_key = env_api_key + if not path and not (host and port) and not (url and api_key): raise ValueError("Either 'host' and 'port' or 'url' and 'api_key' or 'path' must be provided.") return values diff --git a/tests/configs/test_qdrant_config.py b/tests/configs/test_qdrant_config.py new file mode 100644 index 0000000000..8944fea9d1 --- /dev/null +++ b/tests/configs/test_qdrant_config.py @@ -0,0 +1,44 @@ +from mem0.configs.vector_stores.qdrant import QdrantConfig + + +def test_qdrant_config_uses_url_and_api_key_from_environment_when_connection_is_unset(monkeypatch): + monkeypatch.setenv("QDRANT_URL", "http://localhost:6333") + monkeypatch.setenv("QDRANT_API_KEY", "test-key") + + config = QdrantConfig(collection_name="memories", embedding_model_dims=1536, path=None) + + assert config.url == "http://localhost:6333" + assert config.api_key == "test-key" + + +def test_qdrant_config_explicit_values_override_environment(monkeypatch): + monkeypatch.setenv("QDRANT_URL", "http://env-qdrant:6333") + monkeypatch.setenv("QDRANT_API_KEY", "env-key") + + config = QdrantConfig( + collection_name="memories", + embedding_model_dims=1536, + path=None, + url="https://cloud.qdrant.io", + api_key="explicit-key", + ) + + assert config.url == "https://cloud.qdrant.io" + assert config.api_key == "explicit-key" + + +def test_qdrant_config_keeps_explicit_host_port_when_environment_url_is_set(monkeypatch): + monkeypatch.setenv("QDRANT_URL", "http://env-qdrant:6333") + monkeypatch.setenv("QDRANT_API_KEY", "env-key") + + config = QdrantConfig( + collection_name="memories", + embedding_model_dims=1536, + host="localhost", + port=6333, + ) + + assert config.host == "localhost" + assert config.port == 6333 + assert config.url is None + assert config.api_key is None