vector-inspector 0.2.6__py3-none-any.whl → 0.3.1__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.
Files changed (38) hide show
  1. vector_inspector/config/__init__.py +4 -0
  2. vector_inspector/config/known_embedding_models.json +432 -0
  3. vector_inspector/core/cache_manager.py +159 -0
  4. vector_inspector/core/connection_manager.py +277 -0
  5. vector_inspector/core/connections/__init__.py +2 -1
  6. vector_inspector/core/connections/base_connection.py +42 -1
  7. vector_inspector/core/connections/chroma_connection.py +137 -16
  8. vector_inspector/core/connections/pinecone_connection.py +768 -0
  9. vector_inspector/core/connections/qdrant_connection.py +62 -8
  10. vector_inspector/core/embedding_providers/__init__.py +14 -0
  11. vector_inspector/core/embedding_providers/base_provider.py +128 -0
  12. vector_inspector/core/embedding_providers/clip_provider.py +260 -0
  13. vector_inspector/core/embedding_providers/provider_factory.py +176 -0
  14. vector_inspector/core/embedding_providers/sentence_transformer_provider.py +203 -0
  15. vector_inspector/core/embedding_utils.py +167 -0
  16. vector_inspector/core/model_registry.py +205 -0
  17. vector_inspector/services/backup_restore_service.py +19 -29
  18. vector_inspector/services/credential_service.py +130 -0
  19. vector_inspector/services/filter_service.py +1 -1
  20. vector_inspector/services/profile_service.py +409 -0
  21. vector_inspector/services/settings_service.py +136 -1
  22. vector_inspector/ui/components/connection_manager_panel.py +327 -0
  23. vector_inspector/ui/components/profile_manager_panel.py +565 -0
  24. vector_inspector/ui/dialogs/__init__.py +6 -0
  25. vector_inspector/ui/dialogs/cross_db_migration.py +383 -0
  26. vector_inspector/ui/dialogs/embedding_config_dialog.py +315 -0
  27. vector_inspector/ui/dialogs/provider_type_dialog.py +189 -0
  28. vector_inspector/ui/main_window.py +456 -190
  29. vector_inspector/ui/views/connection_view.py +55 -10
  30. vector_inspector/ui/views/info_panel.py +272 -55
  31. vector_inspector/ui/views/metadata_view.py +71 -3
  32. vector_inspector/ui/views/search_view.py +44 -4
  33. vector_inspector/ui/views/visualization_view.py +19 -5
  34. {vector_inspector-0.2.6.dist-info → vector_inspector-0.3.1.dist-info}/METADATA +3 -1
  35. vector_inspector-0.3.1.dist-info/RECORD +55 -0
  36. vector_inspector-0.2.6.dist-info/RECORD +0 -35
  37. {vector_inspector-0.2.6.dist-info → vector_inspector-0.3.1.dist-info}/WHEEL +0 -0
  38. {vector_inspector-0.2.6.dist-info → vector_inspector-0.3.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,189 @@
1
+ """Dialog for selecting embedding provider type (Step 1 of model selection)."""
2
+
3
+ from typing import Optional, Tuple
4
+ from PySide6.QtWidgets import (
5
+ QDialog, QVBoxLayout, QHBoxLayout, QLabel,
6
+ QPushButton, QRadioButton, QButtonGroup, QGroupBox,
7
+ QScrollArea, QWidget
8
+ )
9
+ from PySide6.QtCore import Qt
10
+
11
+ from vector_inspector.core.model_registry import get_model_registry
12
+
13
+
14
+ class ProviderTypeDialog(QDialog):
15
+ """Dialog for selecting the provider/type category before choosing specific model."""
16
+
17
+ # Provider categories with display info
18
+ PROVIDER_CATEGORIES = [
19
+ {
20
+ "id": "sentence-transformer",
21
+ "name": "🤗 Sentence Transformers",
22
+ "description": "Local models from HuggingFace\nNo API key required, runs on your machine",
23
+ "filter_type": "sentence-transformer",
24
+ "icon": "📦"
25
+ },
26
+ {
27
+ "id": "clip",
28
+ "name": "🖼️ CLIP Models",
29
+ "description": "Multimodal embeddings (text + images)\nLocal models, no API key required",
30
+ "filter_type": "clip",
31
+ "icon": "🎨"
32
+ },
33
+ {
34
+ "id": "openai",
35
+ "name": "☁️ OpenAI API",
36
+ "description": "Cloud-based embeddings\nRequires OpenAI API key",
37
+ "filter_type": "openai",
38
+ "icon": "🔑"
39
+ },
40
+ {
41
+ "id": "cohere",
42
+ "name": "☁️ Cohere API",
43
+ "description": "Cloud-based embeddings\nRequires Cohere API key",
44
+ "filter_type": "cohere",
45
+ "icon": "🔑"
46
+ },
47
+ {
48
+ "id": "vertex-ai",
49
+ "name": "☁️ Google Vertex AI",
50
+ "description": "Cloud-based embeddings\nRequires Google Cloud credentials",
51
+ "filter_type": "vertex-ai",
52
+ "icon": "🔑"
53
+ },
54
+ {
55
+ "id": "voyage",
56
+ "name": "☁️ Voyage AI",
57
+ "description": "Cloud-based embeddings\nRequires Voyage API key",
58
+ "filter_type": "voyage",
59
+ "icon": "🔑"
60
+ },
61
+ {
62
+ "id": "custom",
63
+ "name": "✏️ Custom Model",
64
+ "description": "Enter your own model name\nFor models not in the registry",
65
+ "filter_type": None, # Special case
66
+ "icon": "⚙️"
67
+ }
68
+ ]
69
+
70
+ def __init__(self, collection_name: str, vector_dimension: int, parent=None):
71
+ super().__init__(parent)
72
+ self.collection_name = collection_name
73
+ self.vector_dimension = vector_dimension
74
+ self.selected_type = None
75
+
76
+ self.setWindowTitle("Select Embedding Provider Type")
77
+ self.setMinimumWidth(550)
78
+ self.setMinimumHeight(500)
79
+ self._setup_ui()
80
+
81
+ def _setup_ui(self):
82
+ """Setup dialog UI."""
83
+ layout = QVBoxLayout(self)
84
+
85
+ # Header
86
+ header = QLabel(f"<h3>Select Provider Type</h3>")
87
+ layout.addWidget(header)
88
+
89
+ info = QLabel(f"<b>Collection:</b> {self.collection_name}<br>"
90
+ f"<b>Vector Dimension:</b> {self.vector_dimension}")
91
+ layout.addWidget(info)
92
+
93
+ layout.addWidget(QLabel("<i>Choose the type of embedding provider to use:</i>"))
94
+
95
+ # Scroll area for provider options
96
+ scroll = QScrollArea()
97
+ scroll.setWidgetResizable(True)
98
+ scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
99
+
100
+ scroll_widget = QWidget()
101
+ scroll_layout = QVBoxLayout(scroll_widget)
102
+ scroll_layout.setSpacing(10)
103
+
104
+ # Radio button group
105
+ self.button_group = QButtonGroup(self)
106
+
107
+ # Get registry to count models
108
+ registry = get_model_registry()
109
+
110
+ # Create radio buttons for each provider type
111
+ for i, category in enumerate(self.PROVIDER_CATEGORIES):
112
+ provider_id = category["id"]
113
+
114
+ # Count available models for this type + dimension
115
+ if provider_id == "custom":
116
+ count_text = "Enter manually"
117
+ else:
118
+ filter_type = category["filter_type"]
119
+ models = registry.get_models_by_dimension(self.vector_dimension)
120
+ matching = [m for m in models if m.type == filter_type]
121
+ count = len(matching)
122
+
123
+ if count == 0:
124
+ continue # Skip categories with no models for this dimension
125
+
126
+ count_text = f"{count} model{'s' if count != 1 else ''} available"
127
+
128
+ # Create group box for this option
129
+ group = QGroupBox()
130
+ group_layout = QVBoxLayout()
131
+
132
+ # Radio button
133
+ radio = QRadioButton(category["name"])
134
+ radio.setProperty("provider_id", provider_id)
135
+ self.button_group.addButton(radio, i)
136
+ group_layout.addWidget(radio)
137
+
138
+ # Description
139
+ desc_label = QLabel(category["description"])
140
+ desc_label.setStyleSheet("color: gray; margin-left: 25px;")
141
+ desc_label.setWordWrap(True)
142
+ group_layout.addWidget(desc_label)
143
+
144
+ # Count
145
+ count_label = QLabel(f"<b>{count_text}</b>")
146
+ count_label.setStyleSheet("margin-left: 25px; color: #0066cc;")
147
+ group_layout.addWidget(count_label)
148
+
149
+ group.setLayout(group_layout)
150
+ scroll_layout.addWidget(group)
151
+
152
+ scroll_layout.addStretch()
153
+ scroll.setWidget(scroll_widget)
154
+ layout.addWidget(scroll)
155
+
156
+ # Buttons
157
+ button_layout = QHBoxLayout()
158
+ button_layout.addStretch()
159
+
160
+ cancel_btn = QPushButton("Cancel")
161
+ cancel_btn.clicked.connect(self.reject)
162
+
163
+ self.next_btn = QPushButton("Next →")
164
+ self.next_btn.clicked.connect(self._on_next)
165
+ self.next_btn.setEnabled(False)
166
+ self.next_btn.setDefault(True)
167
+
168
+ # Enable Next when selection is made
169
+ self.button_group.buttonClicked.connect(lambda: self.next_btn.setEnabled(True))
170
+
171
+ button_layout.addWidget(cancel_btn)
172
+ button_layout.addWidget(self.next_btn)
173
+
174
+ layout.addLayout(button_layout)
175
+
176
+ def _on_next(self):
177
+ """Handle Next button click."""
178
+ selected_button = self.button_group.checkedButton()
179
+ if selected_button:
180
+ self.selected_type = selected_button.property("provider_id")
181
+ self.accept()
182
+
183
+ def get_selected_type(self) -> Optional[str]:
184
+ """Get the selected provider type ID.
185
+
186
+ Returns:
187
+ Provider type ID or None if cancelled
188
+ """
189
+ return self.selected_type