vector-inspector 0.3.11__py3-none-any.whl → 0.3.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vector_inspector/__init__.py +1 -1
- vector_inspector/core/connection_manager.py +91 -19
- vector_inspector/core/connections/base_connection.py +43 -43
- vector_inspector/core/connections/chroma_connection.py +1 -1
- vector_inspector/core/connections/pgvector_connection.py +11 -171
- vector_inspector/core/connections/pinecone_connection.py +596 -99
- vector_inspector/core/connections/qdrant_connection.py +35 -44
- vector_inspector/core/embedding_utils.py +14 -5
- vector_inspector/core/logging.py +3 -1
- vector_inspector/main.py +42 -15
- vector_inspector/services/backup_restore_service.py +228 -15
- vector_inspector/services/settings_service.py +71 -19
- vector_inspector/ui/components/backup_restore_dialog.py +215 -101
- vector_inspector/ui/components/connection_manager_panel.py +155 -14
- vector_inspector/ui/dialogs/cross_db_migration.py +126 -99
- vector_inspector/ui/dialogs/settings_dialog.py +13 -6
- vector_inspector/ui/loading_screen.py +169 -0
- vector_inspector/ui/main_window.py +44 -19
- vector_inspector/ui/services/dialog_service.py +1 -0
- vector_inspector/ui/views/collection_browser.py +36 -34
- vector_inspector/ui/views/connection_view.py +7 -1
- vector_inspector/ui/views/info_panel.py +118 -52
- vector_inspector/ui/views/metadata_view.py +30 -31
- vector_inspector/ui/views/search_view.py +20 -19
- vector_inspector/ui/views/visualization_view.py +18 -15
- {vector_inspector-0.3.11.dist-info → vector_inspector-0.3.12.dist-info}/METADATA +17 -4
- {vector_inspector-0.3.11.dist-info → vector_inspector-0.3.12.dist-info}/RECORD +30 -28
- vector_inspector-0.3.12.dist-info/licenses/LICENSE +1 -0
- {vector_inspector-0.3.11.dist-info → vector_inspector-0.3.12.dist-info}/WHEEL +0 -0
- {vector_inspector-0.3.11.dist-info → vector_inspector-0.3.12.dist-info}/entry_points.txt +0 -0
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
"""Service for persisting application settings."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
import base64
|
|
5
|
-
|
|
4
|
+
import json
|
|
6
5
|
from pathlib import Path
|
|
7
|
-
from typing import
|
|
6
|
+
from typing import Any, Optional
|
|
7
|
+
|
|
8
|
+
from PySide6.QtCore import QObject, Signal
|
|
9
|
+
|
|
8
10
|
from vector_inspector.core.cache_manager import invalidate_cache_on_settings_change
|
|
9
11
|
from vector_inspector.core.logging import log_error
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class SettingsService:
|
|
13
|
-
"""Handles loading and saving application settings.
|
|
15
|
+
"""Handles loading and saving application settings.
|
|
16
|
+
|
|
17
|
+
This is a singleton - all instances share the same settings data.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
_instance = None
|
|
21
|
+
_initialized = False
|
|
22
|
+
|
|
23
|
+
def __new__(cls):
|
|
24
|
+
"""Ensure only one instance exists (singleton pattern)."""
|
|
25
|
+
if cls._instance is None:
|
|
26
|
+
cls._instance = super().__new__(cls)
|
|
27
|
+
return cls._instance
|
|
14
28
|
|
|
15
29
|
def __init__(self):
|
|
16
30
|
"""Initialize settings service."""
|
|
31
|
+
# Only initialize once
|
|
32
|
+
if SettingsService._initialized:
|
|
33
|
+
return
|
|
34
|
+
SettingsService._initialized = True
|
|
17
35
|
|
|
18
36
|
# Expose a shared QObject-based signal emitter so UI can react to
|
|
19
37
|
# settings changes without polling.
|
|
@@ -28,14 +46,14 @@ class SettingsService:
|
|
|
28
46
|
|
|
29
47
|
self.settings_dir = Path.home() / ".vector-inspector"
|
|
30
48
|
self.settings_file = self.settings_dir / "settings.json"
|
|
31
|
-
self.settings:
|
|
49
|
+
self.settings: dict[str, Any] = {}
|
|
32
50
|
self._load_settings()
|
|
33
51
|
|
|
34
52
|
def _load_settings(self):
|
|
35
53
|
"""Load settings from file."""
|
|
36
54
|
try:
|
|
37
55
|
if self.settings_file.exists():
|
|
38
|
-
with open(self.settings_file,
|
|
56
|
+
with open(self.settings_file, encoding="utf-8") as f:
|
|
39
57
|
self.settings = json.load(f)
|
|
40
58
|
except Exception as e:
|
|
41
59
|
log_error("Failed to load settings: %s", e)
|
|
@@ -52,11 +70,11 @@ class SettingsService:
|
|
|
52
70
|
except Exception as e:
|
|
53
71
|
log_error("Failed to save settings: %s", e)
|
|
54
72
|
|
|
55
|
-
def get_last_connection(self) -> Optional[
|
|
73
|
+
def get_last_connection(self) -> Optional[dict[str, Any]]:
|
|
56
74
|
"""Get the last connection configuration."""
|
|
57
75
|
return self.settings.get("last_connection")
|
|
58
76
|
|
|
59
|
-
def save_last_connection(self, config:
|
|
77
|
+
def save_last_connection(self, config: dict[str, Any]):
|
|
60
78
|
"""Save the last connection configuration."""
|
|
61
79
|
self.settings["last_connection"] = config
|
|
62
80
|
self._save_settings()
|
|
@@ -166,7 +184,7 @@ class SettingsService:
|
|
|
166
184
|
|
|
167
185
|
def save_embedding_model(
|
|
168
186
|
self,
|
|
169
|
-
|
|
187
|
+
profile_name: str,
|
|
170
188
|
collection_name: str,
|
|
171
189
|
model_name: str,
|
|
172
190
|
model_type: str = "user-configured",
|
|
@@ -174,7 +192,7 @@ class SettingsService:
|
|
|
174
192
|
"""Save embedding model mapping for a collection.
|
|
175
193
|
|
|
176
194
|
Args:
|
|
177
|
-
|
|
195
|
+
profile_name: Profile/connection name
|
|
178
196
|
collection_name: Collection name
|
|
179
197
|
model_name: Embedding model name (e.g., 'sentence-transformers/all-MiniLM-L6-v2')
|
|
180
198
|
model_type: Type of configuration ('user-configured', 'auto-detected', 'stored')
|
|
@@ -182,7 +200,7 @@ class SettingsService:
|
|
|
182
200
|
if "collection_embedding_models" not in self.settings:
|
|
183
201
|
self.settings["collection_embedding_models"] = {}
|
|
184
202
|
|
|
185
|
-
collection_key = f"{
|
|
203
|
+
collection_key = f"{profile_name}:{collection_name}"
|
|
186
204
|
self.settings["collection_embedding_models"][collection_key] = {
|
|
187
205
|
"model": model_name,
|
|
188
206
|
"type": model_type,
|
|
@@ -191,35 +209,69 @@ class SettingsService:
|
|
|
191
209
|
self._save_settings()
|
|
192
210
|
|
|
193
211
|
def get_embedding_model(
|
|
194
|
-
self,
|
|
195
|
-
|
|
212
|
+
self,
|
|
213
|
+
profile_name: str,
|
|
214
|
+
collection_name: str,
|
|
215
|
+
) -> Optional[dict[str, Any]]:
|
|
196
216
|
"""Get embedding model mapping for a collection.
|
|
197
217
|
|
|
198
218
|
Args:
|
|
199
|
-
|
|
219
|
+
profile_name: Profile/connection name
|
|
200
220
|
collection_name: Collection name
|
|
201
221
|
|
|
202
222
|
Returns:
|
|
203
223
|
Dictionary with 'model', 'type', and 'timestamp' or None
|
|
204
224
|
"""
|
|
205
225
|
collection_models = self.settings.get("collection_embedding_models", {})
|
|
206
|
-
collection_key = f"{
|
|
226
|
+
collection_key = f"{profile_name}:{collection_name}"
|
|
207
227
|
return collection_models.get(collection_key)
|
|
208
228
|
|
|
209
|
-
def remove_embedding_model(
|
|
229
|
+
def remove_embedding_model(
|
|
230
|
+
self,
|
|
231
|
+
profile_name: str,
|
|
232
|
+
collection_name: str,
|
|
233
|
+
):
|
|
210
234
|
"""Remove embedding model mapping for a collection.
|
|
211
235
|
|
|
212
236
|
Args:
|
|
213
|
-
|
|
237
|
+
profile_name: Profile/connection name
|
|
214
238
|
collection_name: Collection name
|
|
215
239
|
"""
|
|
216
240
|
if "collection_embedding_models" not in self.settings:
|
|
217
241
|
return
|
|
218
242
|
|
|
219
|
-
collection_key = f"{
|
|
243
|
+
collection_key = f"{profile_name}:{collection_name}"
|
|
220
244
|
self.settings["collection_embedding_models"].pop(collection_key, None)
|
|
221
245
|
self._save_settings()
|
|
222
246
|
|
|
247
|
+
def remove_profile_settings(self, profile_name: str):
|
|
248
|
+
"""Remove all settings for a profile (e.g., when profile is deleted).
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
profile_name: Profile/connection name
|
|
252
|
+
"""
|
|
253
|
+
if "collection_embedding_models" not in self.settings:
|
|
254
|
+
return
|
|
255
|
+
|
|
256
|
+
# Remove all keys that start with profile_name:
|
|
257
|
+
prefix = f"{profile_name}:"
|
|
258
|
+
keys_to_remove = [
|
|
259
|
+
key for key in self.settings["collection_embedding_models"] if key.startswith(prefix)
|
|
260
|
+
]
|
|
261
|
+
|
|
262
|
+
for key in keys_to_remove:
|
|
263
|
+
self.settings["collection_embedding_models"].pop(key, None)
|
|
264
|
+
|
|
265
|
+
if keys_to_remove:
|
|
266
|
+
self._save_settings()
|
|
267
|
+
from vector_inspector.core.logging import log_info
|
|
268
|
+
|
|
269
|
+
log_info(
|
|
270
|
+
"Removed %d embedding model settings for profile: %s",
|
|
271
|
+
len(keys_to_remove),
|
|
272
|
+
profile_name,
|
|
273
|
+
)
|
|
274
|
+
|
|
223
275
|
def _get_timestamp(self) -> str:
|
|
224
276
|
"""Get current timestamp as ISO string."""
|
|
225
277
|
from datetime import datetime
|
|
@@ -267,7 +319,7 @@ class SettingsService:
|
|
|
267
319
|
)
|
|
268
320
|
self._save_settings()
|
|
269
321
|
|
|
270
|
-
def get_custom_embedding_models(self, dimension: Optional[int] = None) ->
|
|
322
|
+
def get_custom_embedding_models(self, dimension: Optional[int] = None) -> list[dict[str, Any]]:
|
|
271
323
|
"""Get list of custom embedding models.
|
|
272
324
|
|
|
273
325
|
Args:
|