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.
- vector_inspector/config/__init__.py +4 -0
- vector_inspector/config/known_embedding_models.json +432 -0
- vector_inspector/core/cache_manager.py +159 -0
- vector_inspector/core/connection_manager.py +277 -0
- vector_inspector/core/connections/__init__.py +2 -1
- vector_inspector/core/connections/base_connection.py +42 -1
- vector_inspector/core/connections/chroma_connection.py +137 -16
- vector_inspector/core/connections/pinecone_connection.py +768 -0
- vector_inspector/core/connections/qdrant_connection.py +62 -8
- vector_inspector/core/embedding_providers/__init__.py +14 -0
- vector_inspector/core/embedding_providers/base_provider.py +128 -0
- vector_inspector/core/embedding_providers/clip_provider.py +260 -0
- vector_inspector/core/embedding_providers/provider_factory.py +176 -0
- vector_inspector/core/embedding_providers/sentence_transformer_provider.py +203 -0
- vector_inspector/core/embedding_utils.py +167 -0
- vector_inspector/core/model_registry.py +205 -0
- vector_inspector/services/backup_restore_service.py +19 -29
- vector_inspector/services/credential_service.py +130 -0
- vector_inspector/services/filter_service.py +1 -1
- vector_inspector/services/profile_service.py +409 -0
- vector_inspector/services/settings_service.py +136 -1
- vector_inspector/ui/components/connection_manager_panel.py +327 -0
- vector_inspector/ui/components/profile_manager_panel.py +565 -0
- vector_inspector/ui/dialogs/__init__.py +6 -0
- vector_inspector/ui/dialogs/cross_db_migration.py +383 -0
- vector_inspector/ui/dialogs/embedding_config_dialog.py +315 -0
- vector_inspector/ui/dialogs/provider_type_dialog.py +189 -0
- vector_inspector/ui/main_window.py +456 -190
- vector_inspector/ui/views/connection_view.py +55 -10
- vector_inspector/ui/views/info_panel.py +272 -55
- vector_inspector/ui/views/metadata_view.py +71 -3
- vector_inspector/ui/views/search_view.py +44 -4
- vector_inspector/ui/views/visualization_view.py +19 -5
- {vector_inspector-0.2.6.dist-info → vector_inspector-0.3.1.dist-info}/METADATA +3 -1
- vector_inspector-0.3.1.dist-info/RECORD +55 -0
- vector_inspector-0.2.6.dist-info/RECORD +0 -35
- {vector_inspector-0.2.6.dist-info → vector_inspector-0.3.1.dist-info}/WHEEL +0 -0
- {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
|