Make qdrant the default vector db (#1285)
* Make qdrant the default vector db --------- Co-authored-by: Pablo Orgaz <pabloogc@gmail.com> Co-authored-by: lopagela <lpglm@orange.fr>
This commit is contained in:
		
							parent
							
								
									f1cbff0fb7
								
							
						
					
					
						commit
						510caa576b
					
				|  | @ -1,15 +1,16 @@ | |||
| ## Vectorstores | ||||
| PrivateGPT supports [Chroma](https://www.trychroma.com/), [Qdrant](https://qdrant.tech/) as vectorstore providers. Chroma being the default. | ||||
| PrivateGPT supports [Qdrant](https://qdrant.tech/) and [Chroma](https://www.trychroma.com/) as vectorstore providers. Qdrant being the default. | ||||
| 
 | ||||
| In order to select one or the other, set the `vectorstore.database` property in the `settings.yaml` file to `qdrant` or `chroma`. | ||||
| 
 | ||||
| ```yaml | ||||
| vectorstore: | ||||
|   database: qdrant | ||||
| ``` | ||||
| 
 | ||||
| ### Qdrant configuration | ||||
| 
 | ||||
| To enable Qdrant, set the `vectorstore.database` property in the `settings.yaml` file to `qdrant` and install the `qdrant` extra. | ||||
| 
 | ||||
| ```bash | ||||
| poetry install --extras qdrant | ||||
| ``` | ||||
| 
 | ||||
| By default Qdrant tries to connect to an instance at `http://localhost:3000`. | ||||
| To enable Qdrant, set the `vectorstore.database` property in the `settings.yaml` file to `qdrant`. | ||||
| 
 | ||||
| Qdrant settings can be configured by setting values to the `qdrant` property in the `settings.yaml` file. | ||||
| 
 | ||||
|  | @ -28,3 +29,22 @@ The available configuration options are: | |||
| | host         | Host name of Qdrant service. If url and host are not set, defaults to 'localhost'.| | ||||
| | path         | Persistence path for QdrantLocal. Eg. `local_data/private_gpt/qdrant`| | ||||
| | force_disable_check_same_thread         | Force disable check_same_thread for QdrantLocal sqlite connection, defaults to True.| | ||||
| 
 | ||||
| By default Qdrant tries to connect to an instance of Qdrant server at `http://localhost:3000`. | ||||
| 
 | ||||
| To obtain a local setup (disk-based database) without running a Qdrant server, configure the `qdrant.path` value in settings.yaml: | ||||
| 
 | ||||
| ```yaml | ||||
| qdrant: | ||||
|   path: local_data/private_gpt/qdrant | ||||
| ``` | ||||
| 
 | ||||
| ### Chroma configuration | ||||
| 
 | ||||
| To enable Chroma, set the `vectorstore.database` property in the `settings.yaml` file to `chroma` and install the `chroma` extra. | ||||
| 
 | ||||
| ```bash | ||||
| poetry install --extras chroma | ||||
| ``` | ||||
| 
 | ||||
| By default `chroma` will use a disk-based database stored in local_data_path / "chroma_db" (being local_data_path defined in settings.yaml) | ||||
|  | @ -1,4 +1,4 @@ | |||
| # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. | ||||
| # This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. | ||||
| 
 | ||||
| [[package]] | ||||
| name = "accelerate" | ||||
|  | @ -239,7 +239,7 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte | |||
| name = "backoff" | ||||
| version = "2.2.1" | ||||
| description = "Function decoration for backoff and retry" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7,<4.0" | ||||
| files = [ | ||||
|     {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, | ||||
|  | @ -250,7 +250,7 @@ files = [ | |||
| name = "bcrypt" | ||||
| version = "4.0.1" | ||||
| description = "Modern password hashing for your software and your servers" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.6" | ||||
| files = [ | ||||
|     {file = "bcrypt-4.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f"}, | ||||
|  | @ -373,7 +373,7 @@ crt = ["awscrt (==0.19.12)"] | |||
| name = "cachetools" | ||||
| version = "5.3.2" | ||||
| description = "Extensible memoizing collections and decorators" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, | ||||
|  | @ -505,7 +505,7 @@ files = [ | |||
| name = "chroma-hnswlib" | ||||
| version = "0.7.3" | ||||
| description = "Chromas fork of hnswlib" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = "*" | ||||
| files = [ | ||||
|     {file = "chroma-hnswlib-0.7.3.tar.gz", hash = "sha256:b6137bedde49fffda6af93b0297fe00429fc61e5a072b1ed9377f909ed95a932"}, | ||||
|  | @ -542,7 +542,7 @@ numpy = "*" | |||
| name = "chromadb" | ||||
| version = "0.4.17" | ||||
| description = "Chroma." | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.8" | ||||
| files = [ | ||||
|     {file = "chromadb-0.4.17-py3-none-any.whl", hash = "sha256:8cb88162bc6124441ba5a4b93819463a10e9aaafbe05a3286e876cbdc7a7e11d"}, | ||||
|  | @ -1197,7 +1197,7 @@ tqdm = ["tqdm"] | |||
| name = "google-auth" | ||||
| version = "2.23.4" | ||||
| description = "Google Authentication Library" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "google-auth-2.23.4.tar.gz", hash = "sha256:79905d6b1652187def79d491d6e23d0cbb3a21d3c7ba0dbaa9c8a01906b13ff3"}, | ||||
|  | @ -1220,7 +1220,7 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] | |||
| name = "googleapis-common-protos" | ||||
| version = "1.61.0" | ||||
| description = "Common protobufs used in Google APIs" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "googleapis-common-protos-1.61.0.tar.gz", hash = "sha256:8a64866a97f6304a7179873a465d6eee97b7a24ec6cfd78e0f575e96b821240b"}, | ||||
|  | @ -1435,7 +1435,7 @@ protobuf = ["grpcio-tools (>=1.59.3)"] | |||
| name = "grpcio-tools" | ||||
| version = "1.59.3" | ||||
| description = "Protobuf code generator for gRPC" | ||||
| optional = true | ||||
| optional = false | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "grpcio-tools-1.59.3.tar.gz", hash = "sha256:cd160ac4281cd1ae77a2c880377a7728349340b4c91e24285037b57c18e9f651"}, | ||||
|  | @ -1514,7 +1514,7 @@ files = [ | |||
| name = "h2" | ||||
| version = "4.1.0" | ||||
| description = "HTTP/2 State-Machine based protocol implementation" | ||||
| optional = true | ||||
| optional = false | ||||
| python-versions = ">=3.6.1" | ||||
| files = [ | ||||
|     {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, | ||||
|  | @ -1529,7 +1529,7 @@ hyperframe = ">=6.0,<7" | |||
| name = "hpack" | ||||
| version = "4.0.0" | ||||
| description = "Pure-Python HPACK header compression" | ||||
| optional = true | ||||
| optional = false | ||||
| python-versions = ">=3.6.1" | ||||
| files = [ | ||||
|     {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, | ||||
|  | @ -1681,7 +1681,7 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve | |||
| name = "hyperframe" | ||||
| version = "6.0.1" | ||||
| description = "HTTP/2 framing layer for Python" | ||||
| optional = true | ||||
| optional = false | ||||
| python-versions = ">=3.6.1" | ||||
| files = [ | ||||
|     {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, | ||||
|  | @ -1717,7 +1717,7 @@ files = [ | |||
| name = "importlib-metadata" | ||||
| version = "6.8.0" | ||||
| description = "Read metadata from Python packages" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.8" | ||||
| files = [ | ||||
|     {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, | ||||
|  | @ -1974,7 +1974,7 @@ files = [ | |||
| name = "kubernetes" | ||||
| version = "28.1.0" | ||||
| description = "Kubernetes python client" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.6" | ||||
| files = [ | ||||
|     {file = "kubernetes-28.1.0-py2.py3-none-any.whl", hash = "sha256:10f56f8160dcb73647f15fafda268e7f60cf7dbc9f8e46d52fcd46d3beb0c18d"}, | ||||
|  | @ -2233,7 +2233,7 @@ files = [ | |||
| name = "monotonic" | ||||
| version = "1.6" | ||||
| description = "An implementation of time.monotonic() for Python 2 & < 3.3" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = "*" | ||||
| files = [ | ||||
|     {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"}, | ||||
|  | @ -2679,7 +2679,7 @@ files = [ | |||
| name = "oauthlib" | ||||
| version = "3.2.2" | ||||
| description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.6" | ||||
| files = [ | ||||
|     {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, | ||||
|  | @ -2799,7 +2799,7 @@ datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] | |||
| name = "opentelemetry-api" | ||||
| version = "1.21.0" | ||||
| description = "OpenTelemetry Python API" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "opentelemetry_api-1.21.0-py3-none-any.whl", hash = "sha256:4bb86b28627b7e41098f0e93280fe4892a1abed1b79a19aec6f928f39b17dffb"}, | ||||
|  | @ -2814,7 +2814,7 @@ importlib-metadata = ">=6.0,<7.0" | |||
| name = "opentelemetry-exporter-otlp-proto-common" | ||||
| version = "1.21.0" | ||||
| description = "OpenTelemetry Protobuf encoding" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "opentelemetry_exporter_otlp_proto_common-1.21.0-py3-none-any.whl", hash = "sha256:97b1022b38270ec65d11fbfa348e0cd49d12006485c2321ea3b1b7037d42b6ec"}, | ||||
|  | @ -2829,7 +2829,7 @@ opentelemetry-proto = "1.21.0" | |||
| name = "opentelemetry-exporter-otlp-proto-grpc" | ||||
| version = "1.21.0" | ||||
| description = "OpenTelemetry Collector Protobuf over gRPC Exporter" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "opentelemetry_exporter_otlp_proto_grpc-1.21.0-py3-none-any.whl", hash = "sha256:ab37c63d6cb58d6506f76d71d07018eb1f561d83e642a8f5aa53dddf306087a4"}, | ||||
|  | @ -2853,7 +2853,7 @@ test = ["pytest-grpc"] | |||
| name = "opentelemetry-proto" | ||||
| version = "1.21.0" | ||||
| description = "OpenTelemetry Python Proto" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "opentelemetry_proto-1.21.0-py3-none-any.whl", hash = "sha256:32fc4248e83eebd80994e13963e683f25f3b443226336bb12b5b6d53638f50ba"}, | ||||
|  | @ -2867,7 +2867,7 @@ protobuf = ">=3.19,<5.0" | |||
| name = "opentelemetry-sdk" | ||||
| version = "1.21.0" | ||||
| description = "OpenTelemetry Python SDK" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "opentelemetry_sdk-1.21.0-py3-none-any.whl", hash = "sha256:9fe633243a8c655fedace3a0b89ccdfc654c0290ea2d8e839bd5db3131186f73"}, | ||||
|  | @ -2883,7 +2883,7 @@ typing-extensions = ">=3.7.4" | |||
| name = "opentelemetry-semantic-conventions" | ||||
| version = "0.42b0" | ||||
| description = "OpenTelemetry Semantic Conventions" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "opentelemetry_semantic_conventions-0.42b0-py3-none-any.whl", hash = "sha256:5cd719cbfec448af658860796c5d0fcea2fdf0945a2bed2363f42cb1ee39f526"}, | ||||
|  | @ -3003,7 +3003,7 @@ files = [ | |||
| name = "overrides" | ||||
| version = "7.4.0" | ||||
| description = "A decorator to automatically detect mismatch when overriding a method." | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.6" | ||||
| files = [ | ||||
|     {file = "overrides-7.4.0-py3-none-any.whl", hash = "sha256:3ad24583f86d6d7a49049695efe9933e67ba62f0c7625d53c59fa832ce4b8b7d"}, | ||||
|  | @ -3197,7 +3197,7 @@ testing = ["pytest", "pytest-benchmark"] | |||
| name = "portalocker" | ||||
| version = "2.8.2" | ||||
| description = "Wraps the portalocker recipe for easy usage" | ||||
| optional = true | ||||
| optional = false | ||||
| python-versions = ">=3.8" | ||||
| files = [ | ||||
|     {file = "portalocker-2.8.2-py3-none-any.whl", hash = "sha256:cfb86acc09b9aa7c3b43594e19be1345b9d16af3feb08bf92f23d4dce513a28e"}, | ||||
|  | @ -3216,7 +3216,7 @@ tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "p | |||
| name = "posthog" | ||||
| version = "3.0.2" | ||||
| description = "Integrate PostHog into any python application." | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = "*" | ||||
| files = [ | ||||
|     {file = "posthog-3.0.2-py2.py3-none-any.whl", hash = "sha256:a8c0af6f2401fbe50f90e68c4143d0824b54e872de036b1c2f23b5abb39d88ce"}, | ||||
|  | @ -3305,7 +3305,7 @@ test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] | |||
| name = "pulsar-client" | ||||
| version = "3.3.0" | ||||
| description = "Apache Pulsar Python client library" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = "*" | ||||
| files = [ | ||||
|     {file = "pulsar_client-3.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:c31afd3e67a044ff93177df89e08febf214cc965e95ede097d9fe8755af00e01"}, | ||||
|  | @ -3411,7 +3411,7 @@ files = [ | |||
| name = "pyasn1" | ||||
| version = "0.5.0" | ||||
| description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" | ||||
| files = [ | ||||
|     {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"}, | ||||
|  | @ -3422,7 +3422,7 @@ files = [ | |||
| name = "pyasn1-modules" | ||||
| version = "0.3.0" | ||||
| description = "A collection of ASN.1-based protocols modules" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" | ||||
| files = [ | ||||
|     {file = "pyasn1_modules-0.3.0-py2.py3-none-any.whl", hash = "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"}, | ||||
|  | @ -3662,7 +3662,7 @@ image = ["Pillow (>=8.0.0)"] | |||
| name = "pypika" | ||||
| version = "0.48.9" | ||||
| description = "A SQL query builder API for Python" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = "*" | ||||
| files = [ | ||||
|     {file = "PyPika-0.48.9.tar.gz", hash = "sha256:838836a61747e7c8380cd1b7ff638694b7a7335345d0f559b04b2cd832ad5378"}, | ||||
|  | @ -3792,7 +3792,7 @@ files = [ | |||
| name = "pywin32" | ||||
| version = "306" | ||||
| description = "Python for Window Extensions" | ||||
| optional = true | ||||
| optional = false | ||||
| python-versions = "*" | ||||
| files = [ | ||||
|     {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, | ||||
|  | @ -3874,7 +3874,7 @@ files = [ | |||
| name = "qdrant-client" | ||||
| version = "1.6.9" | ||||
| description = "Client library for the Qdrant vector search engine" | ||||
| optional = true | ||||
| optional = false | ||||
| python-versions = ">=3.8,<3.13" | ||||
| files = [ | ||||
|     {file = "qdrant_client-1.6.9-py3-none-any.whl", hash = "sha256:6546f96ceec389375e323586f0948a04183bd494c5c48d0f3daa267b358ad008"}, | ||||
|  | @ -4030,7 +4030,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] | |||
| name = "requests-oauthlib" | ||||
| version = "1.3.1" | ||||
| description = "OAuthlib authentication support for Requests." | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | ||||
| files = [ | ||||
|     {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, | ||||
|  | @ -4192,7 +4192,7 @@ files = [ | |||
| name = "rsa" | ||||
| version = "4.9" | ||||
| description = "Pure-Python RSA implementation" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.6,<4" | ||||
| files = [ | ||||
|     {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, | ||||
|  | @ -5514,7 +5514,7 @@ anyio = ">=3.0.0" | |||
| name = "websocket-client" | ||||
| version = "1.6.4" | ||||
| description = "WebSocket client for Python with low level API options" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.8" | ||||
| files = [ | ||||
|     {file = "websocket-client-1.6.4.tar.gz", hash = "sha256:b3324019b3c28572086c4a319f91d1dcd44e6e11cd340232978c684a7650d0df"}, | ||||
|  | @ -5892,7 +5892,7 @@ multidict = ">=4.0" | |||
| name = "zipp" | ||||
| version = "3.17.0" | ||||
| description = "Backport of pathlib-compatible object wrapper for zip files" | ||||
| optional = false | ||||
| optional = true | ||||
| python-versions = ">=3.8" | ||||
| files = [ | ||||
|     {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, | ||||
|  | @ -5904,9 +5904,9 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link | |||
| testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] | ||||
| 
 | ||||
| [extras] | ||||
| qdrant = ["qdrant-client"] | ||||
| chroma = ["chromadb"] | ||||
| 
 | ||||
| [metadata] | ||||
| lock-version = "2.0" | ||||
| python-versions = ">=3.11,<3.12" | ||||
| content-hash = "62688941bd24b24069b81c596ffb713fbe0427b8eec3f849cf809fdfde2db339" | ||||
| content-hash = "7b9e7bc6e4a9ecbab92e58423c1d6746aa731b681236b1966f986feac3101959" | ||||
|  |  | |||
|  | @ -1,8 +1,6 @@ | |||
| import logging | ||||
| import typing | ||||
| 
 | ||||
| import chromadb | ||||
| from chromadb.config import Settings as ChromaSettings | ||||
| from injector import inject, singleton | ||||
| from llama_index import VectorStoreIndex | ||||
| from llama_index.indices.vector_store import VectorIndexRetriever | ||||
|  | @ -43,6 +41,18 @@ class VectorStoreComponent: | |||
|     def __init__(self, settings: Settings) -> None: | ||||
|         match settings.vectorstore.database: | ||||
|             case "chroma": | ||||
|                 try: | ||||
|                     import chromadb  # type: ignore | ||||
|                     from chromadb.config import (  # type: ignore | ||||
|                         Settings as ChromaSettings, | ||||
|                     ) | ||||
|                 except ImportError as e: | ||||
|                     raise ImportError( | ||||
|                         "'chromadb' is not installed." | ||||
|                         "To use PrivateGPT with Chroma, install the 'chroma' extra." | ||||
|                         "`poetry install --extras chroma`" | ||||
|                     ) from e | ||||
| 
 | ||||
|                 chroma_settings = ChromaSettings(anonymized_telemetry=False) | ||||
|                 chroma_client = chromadb.PersistentClient( | ||||
|                     path=str((local_data_path / "chroma_db").absolute()), | ||||
|  | @ -60,15 +70,9 @@ class VectorStoreComponent: | |||
|                 ) | ||||
| 
 | ||||
|             case "qdrant": | ||||
|                 try: | ||||
|                     from llama_index.vector_stores.qdrant import QdrantVectorStore | ||||
|                     from qdrant_client import QdrantClient  # type: ignore | ||||
|                 except ImportError as e: | ||||
|                     raise ImportError( | ||||
|                         "'qdrant_client' is not installed." | ||||
|                         "To use PrivateGPT with Qdrant, install the 'qdrant' extra." | ||||
|                         "`poetry install --extras qdrant`" | ||||
|                     ) from e | ||||
|                 from llama_index.vector_stores.qdrant import QdrantVectorStore | ||||
|                 from qdrant_client import QdrantClient | ||||
| 
 | ||||
|                 if settings.qdrant is None: | ||||
|                     logger.info( | ||||
|                         "Qdrant config not found. Using default settings." | ||||
|  | @ -99,11 +103,16 @@ class VectorStoreComponent: | |||
|         context_filter: ContextFilter | None = None, | ||||
|         similarity_top_k: int = 2, | ||||
|     ) -> VectorIndexRetriever: | ||||
|         # TODO this 'where' is specific to chromadb. Implement other vector stores | ||||
|         # This way we support qdrant (using doc_ids) and chroma (using where clause) | ||||
|         return VectorIndexRetriever( | ||||
|             index=index, | ||||
|             similarity_top_k=similarity_top_k, | ||||
|             doc_ids=context_filter.docs_ids if context_filter else None, | ||||
|             vector_store_kwargs={ | ||||
|                 "where": _chromadb_doc_id_metadata_filter(context_filter) | ||||
|             }, | ||||
|         ) | ||||
| 
 | ||||
|     def close(self) -> None: | ||||
|         if hasattr(self.vector_store.client, "close"): | ||||
|             self.vector_store.client.close() | ||||
|  |  | |||
|  | @ -207,7 +207,12 @@ class IngestService: | |||
|         ) | ||||
| 
 | ||||
|         # Load the index with store_nodes_override=True to be able to delete them | ||||
|         index = load_index_from_storage(self.storage_context, store_nodes_override=True) | ||||
|         index = load_index_from_storage( | ||||
|             storage_context=self.storage_context, | ||||
|             service_context=self.ingest_service_context, | ||||
|             store_nodes_override=True,  # Force store nodes in index and document stores | ||||
|             show_progress=True, | ||||
|         ) | ||||
| 
 | ||||
|         # Delete the document from the index | ||||
|         index.delete_ref_doc(doc_id, delete_from_docstore=True) | ||||
|  |  | |||
|  | @ -13,9 +13,9 @@ pyyaml = "^6.0.1" | |||
| python-multipart = "^0.0.6" | ||||
| pypdf = "^3.16.2" | ||||
| llama-index = { extras = ["local_models"], version = "0.9.3" } | ||||
| chromadb = "^0.4.13" | ||||
| watchdog = "^3.0.0" | ||||
| qdrant-client = {version = "^1.6.9", optional = true} | ||||
| qdrant-client = "^1.6.9" | ||||
| chromadb = {version = "^0.4.13", optional = true} | ||||
| 
 | ||||
| [tool.poetry.group.dev.dependencies] | ||||
| black = "^22" | ||||
|  | @ -44,7 +44,7 @@ torch = ">=2.0.0, !=2.0.1, !=2.1.0" | |||
| transformers = "^4.34.0" | ||||
| 
 | ||||
| [tool.poetry.extras] | ||||
| qdrant = ["qdrant-client"] | ||||
| chroma = ["chromadb"] | ||||
| 
 | ||||
| [build-system] | ||||
| requires = ["poetry-core>=1.0.0"] | ||||
|  | @ -135,6 +135,7 @@ python_version = "3.11" | |||
| strict = true | ||||
| check_untyped_defs = false | ||||
| explicit_package_bases = true | ||||
| warn_unused_ignores = false | ||||
| exclude = ["tests"] | ||||
| 
 | ||||
| [tool.pytest.ini_options] | ||||
|  |  | |||
|  | @ -5,10 +5,12 @@ server: | |||
|     # Dummy secrets used for tests | ||||
|     secret: "foo bar; dummy secret" | ||||
| 
 | ||||
| 
 | ||||
| data: | ||||
|   local_data_folder: local_data/tests | ||||
| 
 | ||||
| qdrant: | ||||
|   path: local_data/tests | ||||
| 
 | ||||
| llm: | ||||
|   mode: mock | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,7 +24,10 @@ llm: | |||
|   mode: local | ||||
| 
 | ||||
| vectorstore: | ||||
|   database: chroma | ||||
|   database: qdrant | ||||
| 
 | ||||
| qdrant: | ||||
|   path: local_data/private_gpt/qdrant | ||||
| 
 | ||||
| local: | ||||
|   llm_hf_repo_id: TheBloke/Mistral-7B-Instruct-v0.1-GGUF | ||||
|  |  | |||
|  | @ -0,0 +1,18 @@ | |||
| import pytest | ||||
| 
 | ||||
| from private_gpt.components.vector_store.vector_store_component import ( | ||||
|     VectorStoreComponent, | ||||
| ) | ||||
| from tests.fixtures.mock_injector import MockInjector | ||||
| 
 | ||||
| 
 | ||||
| @pytest.fixture(autouse=True) | ||||
| def _auto_close_vector_store_client(injector: MockInjector) -> None: | ||||
|     """Auto close VectorStore client after each test. | ||||
| 
 | ||||
|     VectorStore client (qdrant/chromadb) opens a connection the | ||||
|     Database that causes issues when running tests too fast, | ||||
|     so close explicitly after each test. | ||||
|     """ | ||||
|     yield | ||||
|     injector.get(VectorStoreComponent).close() | ||||
|  | @ -1,27 +0,0 @@ | |||
| from unittest.mock import PropertyMock, patch | ||||
| 
 | ||||
| from llama_index import Document | ||||
| 
 | ||||
| from private_gpt.server.ingest.ingest_service import IngestService | ||||
| from tests.fixtures.mock_injector import MockInjector | ||||
| 
 | ||||
| 
 | ||||
| def test_save_many_nodes(injector: MockInjector) -> None: | ||||
|     """This is a specific test for a local Chromadb Vector Database setup. | ||||
| 
 | ||||
|     Extend it when we add support for other vector databases in VectorStoreComponent. | ||||
|     """ | ||||
|     with patch( | ||||
|         "chromadb.api.segment.SegmentAPI.max_batch_size", new_callable=PropertyMock | ||||
|     ) as max_batch_size: | ||||
|         # Make max batch size of Chromadb very small | ||||
|         max_batch_size.return_value = 10 | ||||
| 
 | ||||
|         ingest_service = injector.get(IngestService) | ||||
| 
 | ||||
|         documents = [] | ||||
|         for _i in range(100): | ||||
|             documents.append(Document(text="This is a sentence.")) | ||||
| 
 | ||||
|         ingested_docs = ingest_service._save_docs(documents) | ||||
|         assert len(ingested_docs) == len(documents) | ||||
		Loading…
	
		Reference in New Issue