vector-inspector 0.2.2__tar.gz → 0.2.4__tar.gz
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-0.2.2 → vector_inspector-0.2.4}/PKG-INFO +30 -12
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/README.md +27 -10
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/pyproject.toml +3 -2
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/services/import_export_service.py +30 -14
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/metadata_view.py +99 -26
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/__init__.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/__main__.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/core/__init__.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/core/connections/__init__.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/core/connections/base_connection.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/core/connections/chroma_connection.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/core/connections/qdrant_connection.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/core/connections/template_connection.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/main.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/services/__init__.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/services/backup_restore_service.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/services/filter_service.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/services/settings_service.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/services/visualization_service.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/__init__.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/components/__init__.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/components/backup_restore_dialog.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/components/filter_builder.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/components/item_dialog.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/components/loading_dialog.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/main_window.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/__init__.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/collection_browser.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/connection_view.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/search_view.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/visualization_view.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/tests/test_connections.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/tests/test_filter_service.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/tests/test_settings_service.py +0 -0
- {vector_inspector-0.2.2 → vector_inspector-0.2.4}/tests/vector_inspector.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: vector-inspector
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: A comprehensive desktop application for visualizing, querying, and managing vector database data
|
|
5
5
|
Author-Email: Anthony Dawson <anthonypdawson+github@gmail.com>
|
|
6
6
|
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://
|
|
7
|
+
Project-URL: Homepage, https://vector-inspector.divinedevops.com
|
|
8
8
|
Project-URL: Source, https://github.com/anthony-dawson/vector-inspector
|
|
9
9
|
Project-URL: Issues, https://github.com/anthony-dawson/vector-inspector/issues
|
|
10
10
|
Project-URL: Documentation, https://github.com/anthony-dawson/vector-inspector#readme
|
|
@@ -21,9 +21,13 @@ Requires-Dist: plotly>=5.18.0
|
|
|
21
21
|
Requires-Dist: sentence-transformers>=2.2.0
|
|
22
22
|
Requires-Dist: fastembed>=0.7.4
|
|
23
23
|
Requires-Dist: pyarrow>=14.0.0
|
|
24
|
+
Requires-Dist: pinecone>=8.0.0
|
|
24
25
|
Description-Content-Type: text/markdown
|
|
25
26
|
|
|
27
|
+
|
|
26
28
|
# Vector Inspector
|
|
29
|
+

|
|
30
|
+
[](https://pepy.tech/projects/vector-inspector)
|
|
27
31
|
|
|
28
32
|
|
|
29
33
|
A comprehensive desktop application for visualizing, querying, and managing vector database data. Similar to SQL database viewers, Vector Inspector provides an intuitive GUI for exploring vector embeddings, metadata, and performing similarity searches across multiple vector database providers.
|
|
@@ -137,9 +141,13 @@ For detailed architecture information, see [docs/architecture.md](docs/architect
|
|
|
137
141
|
|
|
138
142
|
## Feature Access
|
|
139
143
|
|
|
140
|
-
Vector Inspector
|
|
144
|
+
Vector Inspector follows a user-friendly monetization model:
|
|
145
|
+
|
|
146
|
+
- **All vector database providers are free** — Try the full app with any database
|
|
147
|
+
- **Core workflows remain free** — Connect, browse, search, visualize, and manage your data
|
|
148
|
+
- **Pro adds power tools** — Advanced analytics, enterprise formats, workflow automation, and collaboration
|
|
141
149
|
|
|
142
|
-
See [FEATURES.md](FEATURES.md) for a
|
|
150
|
+
**Nothing currently in Free will ever move to Pro.** See [FEATURES.md](FEATURES.md) for a detailed comparison.
|
|
143
151
|
|
|
144
152
|
## Roadmap
|
|
145
153
|
|
|
@@ -147,6 +155,7 @@ See [FEATURES.md](FEATURES.md) for a complete feature comparison.
|
|
|
147
155
|
|
|
148
156
|
See [ROADMAP.md](ROADMAP.md) for the complete development roadmap and planned features.
|
|
149
157
|
|
|
158
|
+
|
|
150
159
|
## Installation
|
|
151
160
|
|
|
152
161
|
### From PyPI (Recommended)
|
|
@@ -156,6 +165,22 @@ pip install vector-inspector
|
|
|
156
165
|
vector-inspector
|
|
157
166
|
```
|
|
158
167
|
|
|
168
|
+
### From a Downloaded Wheel or Tarball (e.g., GitHub Release)
|
|
169
|
+
|
|
170
|
+
Download the `.whl` or `.tar.gz` file from the [GitHub Releases](https://github.com/anthonypdawson/vector-inspector/releases) page, then install with:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pip install <your-filename.whl>
|
|
174
|
+
# or
|
|
175
|
+
pip install <your-filename.tar.gz>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
After installation, run the application with:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
vector-inspector
|
|
182
|
+
```
|
|
183
|
+
|
|
159
184
|
### From Source
|
|
160
185
|
|
|
161
186
|
```bash
|
|
@@ -234,15 +259,8 @@ This project draws inspiration from:
|
|
|
234
259
|
|
|
235
260
|
---
|
|
236
261
|
|
|
237
|
-
**Status**: ✅ Phase 2 Complete - Advanced Features Implemented!
|
|
238
262
|
|
|
239
|
-
|
|
240
|
-
- 🔍 Advanced metadata filtering with customizable filter rules (AND/OR logic)
|
|
241
|
-
- ✏️ Double-click to edit items directly in the data browser
|
|
242
|
-
- 📥 Import data from CSV, JSON, and Parquet files
|
|
243
|
-
- 📤 Export filtered data to CSV, JSON, and Parquet formats
|
|
244
|
-
- 💾 Comprehensive backup and restore system for collections
|
|
245
|
-
- 🔄 Metadata filters integrated with search for powerful queries
|
|
263
|
+
See [CHANGELOG.md](CHANGELOG.md) for the latest status and what's new in each release.
|
|
246
264
|
|
|
247
265
|
See [GETTING_STARTED.md](GETTING_STARTED.md) for usage instructions and [IMPLEMENTATION_SUMMARY.md](IMPLEMENTATION_SUMMARY.md) for technical details.
|
|
248
266
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
|
|
1
2
|
# Vector Inspector
|
|
3
|
+

|
|
4
|
+
[](https://pepy.tech/projects/vector-inspector)
|
|
2
5
|
|
|
3
6
|
|
|
4
7
|
A comprehensive desktop application for visualizing, querying, and managing vector database data. Similar to SQL database viewers, Vector Inspector provides an intuitive GUI for exploring vector embeddings, metadata, and performing similarity searches across multiple vector database providers.
|
|
@@ -112,9 +115,13 @@ For detailed architecture information, see [docs/architecture.md](docs/architect
|
|
|
112
115
|
|
|
113
116
|
## Feature Access
|
|
114
117
|
|
|
115
|
-
Vector Inspector
|
|
118
|
+
Vector Inspector follows a user-friendly monetization model:
|
|
119
|
+
|
|
120
|
+
- **All vector database providers are free** — Try the full app with any database
|
|
121
|
+
- **Core workflows remain free** — Connect, browse, search, visualize, and manage your data
|
|
122
|
+
- **Pro adds power tools** — Advanced analytics, enterprise formats, workflow automation, and collaboration
|
|
116
123
|
|
|
117
|
-
See [FEATURES.md](FEATURES.md) for a
|
|
124
|
+
**Nothing currently in Free will ever move to Pro.** See [FEATURES.md](FEATURES.md) for a detailed comparison.
|
|
118
125
|
|
|
119
126
|
## Roadmap
|
|
120
127
|
|
|
@@ -122,6 +129,7 @@ See [FEATURES.md](FEATURES.md) for a complete feature comparison.
|
|
|
122
129
|
|
|
123
130
|
See [ROADMAP.md](ROADMAP.md) for the complete development roadmap and planned features.
|
|
124
131
|
|
|
132
|
+
|
|
125
133
|
## Installation
|
|
126
134
|
|
|
127
135
|
### From PyPI (Recommended)
|
|
@@ -131,6 +139,22 @@ pip install vector-inspector
|
|
|
131
139
|
vector-inspector
|
|
132
140
|
```
|
|
133
141
|
|
|
142
|
+
### From a Downloaded Wheel or Tarball (e.g., GitHub Release)
|
|
143
|
+
|
|
144
|
+
Download the `.whl` or `.tar.gz` file from the [GitHub Releases](https://github.com/anthonypdawson/vector-inspector/releases) page, then install with:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pip install <your-filename.whl>
|
|
148
|
+
# or
|
|
149
|
+
pip install <your-filename.tar.gz>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
After installation, run the application with:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
vector-inspector
|
|
156
|
+
```
|
|
157
|
+
|
|
134
158
|
### From Source
|
|
135
159
|
|
|
136
160
|
```bash
|
|
@@ -209,15 +233,8 @@ This project draws inspiration from:
|
|
|
209
233
|
|
|
210
234
|
---
|
|
211
235
|
|
|
212
|
-
**Status**: ✅ Phase 2 Complete - Advanced Features Implemented!
|
|
213
236
|
|
|
214
|
-
|
|
215
|
-
- 🔍 Advanced metadata filtering with customizable filter rules (AND/OR logic)
|
|
216
|
-
- ✏️ Double-click to edit items directly in the data browser
|
|
217
|
-
- 📥 Import data from CSV, JSON, and Parquet files
|
|
218
|
-
- 📤 Export filtered data to CSV, JSON, and Parquet formats
|
|
219
|
-
- 💾 Comprehensive backup and restore system for collections
|
|
220
|
-
- 🔄 Metadata filters integrated with search for powerful queries
|
|
237
|
+
See [CHANGELOG.md](CHANGELOG.md) for the latest status and what's new in each release.
|
|
221
238
|
|
|
222
239
|
See [GETTING_STARTED.md](GETTING_STARTED.md) for usage instructions and [IMPLEMENTATION_SUMMARY.md](IMPLEMENTATION_SUMMARY.md) for technical details.
|
|
223
240
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vector-inspector"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.4"
|
|
4
4
|
description = "A comprehensive desktop application for visualizing, querying, and managing vector database data"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Anthony Dawson", email = "anthonypdawson+github@gmail.com" },
|
|
@@ -18,6 +18,7 @@ dependencies = [
|
|
|
18
18
|
"sentence-transformers>=2.2.0",
|
|
19
19
|
"fastembed>=0.7.4",
|
|
20
20
|
"pyarrow>=14.0.0",
|
|
21
|
+
"pinecone>=8.0.0",
|
|
21
22
|
]
|
|
22
23
|
requires-python = "==3.12.*"
|
|
23
24
|
readme = "README.md"
|
|
@@ -26,7 +27,7 @@ readme = "README.md"
|
|
|
26
27
|
text = "MIT"
|
|
27
28
|
|
|
28
29
|
[project.urls]
|
|
29
|
-
Homepage = "https://
|
|
30
|
+
Homepage = "https://vector-inspector.divinedevops.com"
|
|
30
31
|
Source = "https://github.com/anthony-dawson/vector-inspector"
|
|
31
32
|
Issues = "https://github.com/anthony-dawson/vector-inspector/issues"
|
|
32
33
|
Documentation = "https://github.com/anthony-dawson/vector-inspector#readme"
|
|
@@ -5,6 +5,7 @@ import csv
|
|
|
5
5
|
from typing import Dict, Any, List, Optional
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
import pandas as pd
|
|
8
|
+
import numpy as np
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class ImportExportService:
|
|
@@ -36,9 +37,13 @@ class ImportExportService:
|
|
|
36
37
|
"document": documents[i] if i < len(documents) else None,
|
|
37
38
|
"metadata": metadatas[i] if i < len(metadatas) else {},
|
|
38
39
|
}
|
|
39
|
-
# Optionally include embeddings
|
|
40
|
-
if embeddings and i < len(embeddings):
|
|
41
|
-
|
|
40
|
+
# Optionally include embeddings (convert numpy arrays to lists)
|
|
41
|
+
if len(embeddings) > 0 and i < len(embeddings):
|
|
42
|
+
embedding = embeddings[i]
|
|
43
|
+
# Convert numpy array to list if needed
|
|
44
|
+
if isinstance(embedding, np.ndarray):
|
|
45
|
+
embedding = embedding.tolist()
|
|
46
|
+
item["embedding"] = embedding
|
|
42
47
|
export_data.append(item)
|
|
43
48
|
|
|
44
49
|
# Write to file
|
|
@@ -82,9 +87,13 @@ class ImportExportService:
|
|
|
82
87
|
for key, value in metadatas[i].items():
|
|
83
88
|
row[f"metadata_{key}"] = value
|
|
84
89
|
|
|
85
|
-
# Optionally add embeddings
|
|
86
|
-
if include_embeddings and embeddings and i < len(embeddings):
|
|
87
|
-
|
|
90
|
+
# Optionally add embeddings (convert numpy arrays to lists)
|
|
91
|
+
if include_embeddings and len(embeddings) > 0 and i < len(embeddings):
|
|
92
|
+
embedding = embeddings[i]
|
|
93
|
+
# Convert numpy array to list if needed
|
|
94
|
+
if isinstance(embedding, np.ndarray):
|
|
95
|
+
embedding = embedding.tolist()
|
|
96
|
+
row["embedding"] = json.dumps(embedding)
|
|
88
97
|
|
|
89
98
|
rows.append(row)
|
|
90
99
|
|
|
@@ -118,17 +127,24 @@ class ImportExportService:
|
|
|
118
127
|
# Prepare data for DataFrame
|
|
119
128
|
df_data = {
|
|
120
129
|
"id": ids,
|
|
121
|
-
"document": documents if documents else [None] * len(ids),
|
|
130
|
+
"document": documents if len(documents) > 0 else [None] * len(ids),
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
# Add metadata fields as separate columns
|
|
125
|
-
if metadatas and metadatas[0]:
|
|
134
|
+
if len(metadatas) > 0 and metadatas[0]:
|
|
126
135
|
for key in metadatas[0].keys():
|
|
127
136
|
df_data[f"metadata_{key}"] = [m.get(key) if m else None for m in metadatas]
|
|
128
137
|
|
|
129
|
-
# Add embeddings as a column
|
|
130
|
-
if embeddings:
|
|
131
|
-
|
|
138
|
+
# Add embeddings as a column (convert numpy arrays to lists for compatibility)
|
|
139
|
+
if len(embeddings) > 0:
|
|
140
|
+
# Convert numpy arrays to lists if needed
|
|
141
|
+
embedding_list = []
|
|
142
|
+
for emb in embeddings:
|
|
143
|
+
if isinstance(emb, np.ndarray):
|
|
144
|
+
embedding_list.append(emb.tolist())
|
|
145
|
+
else:
|
|
146
|
+
embedding_list.append(emb)
|
|
147
|
+
df_data["embedding"] = embedding_list
|
|
132
148
|
|
|
133
149
|
# Create DataFrame and save
|
|
134
150
|
df = pd.DataFrame(df_data)
|
|
@@ -173,7 +189,7 @@ class ImportExportService:
|
|
|
173
189
|
"metadatas": metadatas,
|
|
174
190
|
}
|
|
175
191
|
|
|
176
|
-
if embeddings:
|
|
192
|
+
if len(embeddings) > 0:
|
|
177
193
|
result["embeddings"] = embeddings
|
|
178
194
|
|
|
179
195
|
return result
|
|
@@ -227,7 +243,7 @@ class ImportExportService:
|
|
|
227
243
|
"metadatas": metadatas,
|
|
228
244
|
}
|
|
229
245
|
|
|
230
|
-
if embeddings:
|
|
246
|
+
if len(embeddings) > 0:
|
|
231
247
|
result["embeddings"] = embeddings
|
|
232
248
|
|
|
233
249
|
return result
|
|
@@ -277,7 +293,7 @@ class ImportExportService:
|
|
|
277
293
|
"metadatas": metadatas,
|
|
278
294
|
}
|
|
279
295
|
|
|
280
|
-
if embeddings:
|
|
296
|
+
if len(embeddings) > 0:
|
|
281
297
|
result["embeddings"] = embeddings
|
|
282
298
|
|
|
283
299
|
return result
|
{vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/metadata_view.py
RENAMED
|
@@ -15,6 +15,7 @@ from vector_inspector.ui.components.loading_dialog import LoadingDialog
|
|
|
15
15
|
from vector_inspector.ui.components.filter_builder import FilterBuilder
|
|
16
16
|
from vector_inspector.services.import_export_service import ImportExportService
|
|
17
17
|
from vector_inspector.services.filter_service import apply_client_side_filters
|
|
18
|
+
from vector_inspector.services.settings_service import SettingsService
|
|
18
19
|
from PySide6.QtWidgets import QApplication
|
|
19
20
|
|
|
20
21
|
|
|
@@ -29,6 +30,7 @@ class MetadataView(QWidget):
|
|
|
29
30
|
self.page_size = 50
|
|
30
31
|
self.current_page = 0
|
|
31
32
|
self.loading_dialog = LoadingDialog("Loading data...", self)
|
|
33
|
+
self.settings_service = SettingsService()
|
|
32
34
|
|
|
33
35
|
# Debounce timer for filter changes
|
|
34
36
|
self.filter_reload_timer = QTimer()
|
|
@@ -426,33 +428,41 @@ class MetadataView(QWidget):
|
|
|
426
428
|
QMessageBox.warning(self, "Error", "Failed to update item.")
|
|
427
429
|
|
|
428
430
|
def _export_data(self, format_type: str):
|
|
429
|
-
"""Export
|
|
431
|
+
"""Export current table data to file (visible rows or selected rows)."""
|
|
430
432
|
if not self.current_collection:
|
|
431
433
|
QMessageBox.warning(self, "No Collection", "Please select a collection first.")
|
|
432
434
|
return
|
|
433
|
-
|
|
434
|
-
# Get all data (not just current page)
|
|
435
|
-
self.loading_dialog.show_loading("Exporting data...")
|
|
436
|
-
QApplication.processEvents()
|
|
437
435
|
|
|
438
|
-
|
|
439
|
-
# Get filter if active
|
|
440
|
-
where_filter = None
|
|
441
|
-
if self.filter_group.isChecked() and self.filter_builder.has_filters():
|
|
442
|
-
where_filter = self.filter_builder.get_filter()
|
|
443
|
-
|
|
444
|
-
# Fetch all data
|
|
445
|
-
all_data = self.connection.get_all_items(
|
|
446
|
-
self.current_collection,
|
|
447
|
-
where=where_filter
|
|
448
|
-
)
|
|
449
|
-
finally:
|
|
450
|
-
self.loading_dialog.hide_loading()
|
|
451
|
-
|
|
452
|
-
if not all_data or not all_data.get("ids"):
|
|
436
|
+
if not self.current_data or not self.current_data.get("ids"):
|
|
453
437
|
QMessageBox.warning(self, "No Data", "No data to export.")
|
|
454
438
|
return
|
|
455
439
|
|
|
440
|
+
# Check if there are selected rows
|
|
441
|
+
selected_rows = self.table.selectionModel().selectedRows()
|
|
442
|
+
|
|
443
|
+
if selected_rows:
|
|
444
|
+
# Export only selected rows
|
|
445
|
+
export_data = {
|
|
446
|
+
"ids": [],
|
|
447
|
+
"documents": [],
|
|
448
|
+
"metadatas": [],
|
|
449
|
+
"embeddings": []
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
for index in selected_rows:
|
|
453
|
+
row = index.row()
|
|
454
|
+
if row < len(self.current_data["ids"]):
|
|
455
|
+
export_data["ids"].append(self.current_data["ids"][row])
|
|
456
|
+
if "documents" in self.current_data and row < len(self.current_data["documents"]):
|
|
457
|
+
export_data["documents"].append(self.current_data["documents"][row])
|
|
458
|
+
if "metadatas" in self.current_data and row < len(self.current_data["metadatas"]):
|
|
459
|
+
export_data["metadatas"].append(self.current_data["metadatas"][row])
|
|
460
|
+
if "embeddings" in self.current_data and row < len(self.current_data["embeddings"]):
|
|
461
|
+
export_data["embeddings"].append(self.current_data["embeddings"][row])
|
|
462
|
+
else:
|
|
463
|
+
# Export all visible data from current table
|
|
464
|
+
export_data = self.current_data
|
|
465
|
+
|
|
456
466
|
# Select file path
|
|
457
467
|
file_filters = {
|
|
458
468
|
"json": "JSON Files (*.json)",
|
|
@@ -460,10 +470,14 @@ class MetadataView(QWidget):
|
|
|
460
470
|
"parquet": "Parquet Files (*.parquet)"
|
|
461
471
|
}
|
|
462
472
|
|
|
473
|
+
# Get last used directory from settings
|
|
474
|
+
last_dir = self.settings_service.get("last_import_export_dir", "")
|
|
475
|
+
default_path = f"{last_dir}/{self.current_collection}.{format_type}" if last_dir else f"{self.current_collection}.{format_type}"
|
|
476
|
+
|
|
463
477
|
file_path, _ = QFileDialog.getSaveFileName(
|
|
464
478
|
self,
|
|
465
479
|
f"Export to {format_type.upper()}",
|
|
466
|
-
|
|
480
|
+
default_path,
|
|
467
481
|
file_filters[format_type]
|
|
468
482
|
)
|
|
469
483
|
|
|
@@ -475,17 +489,21 @@ class MetadataView(QWidget):
|
|
|
475
489
|
success = False
|
|
476
490
|
|
|
477
491
|
if format_type == "json":
|
|
478
|
-
success = service.export_to_json(
|
|
492
|
+
success = service.export_to_json(export_data, file_path)
|
|
479
493
|
elif format_type == "csv":
|
|
480
|
-
success = service.export_to_csv(
|
|
494
|
+
success = service.export_to_csv(export_data, file_path)
|
|
481
495
|
elif format_type == "parquet":
|
|
482
|
-
success = service.export_to_parquet(
|
|
496
|
+
success = service.export_to_parquet(export_data, file_path)
|
|
483
497
|
|
|
484
498
|
if success:
|
|
499
|
+
# Save the directory for next time
|
|
500
|
+
from pathlib import Path
|
|
501
|
+
self.settings_service.set("last_import_export_dir", str(Path(file_path).parent))
|
|
502
|
+
|
|
485
503
|
QMessageBox.information(
|
|
486
504
|
self,
|
|
487
505
|
"Export Successful",
|
|
488
|
-
f"Exported {len(
|
|
506
|
+
f"Exported {len(export_data['ids'])} items to {file_path}"
|
|
489
507
|
)
|
|
490
508
|
else:
|
|
491
509
|
QMessageBox.warning(self, "Export Failed", "Failed to export data.")
|
|
@@ -503,10 +521,13 @@ class MetadataView(QWidget):
|
|
|
503
521
|
"parquet": "Parquet Files (*.parquet)"
|
|
504
522
|
}
|
|
505
523
|
|
|
524
|
+
# Get last used directory from settings
|
|
525
|
+
last_dir = self.settings_service.get("last_import_export_dir", "")
|
|
526
|
+
|
|
506
527
|
file_path, _ = QFileDialog.getOpenFileName(
|
|
507
528
|
self,
|
|
508
529
|
f"Import from {format_type.upper()}",
|
|
509
|
-
|
|
530
|
+
last_dir,
|
|
510
531
|
file_filters[format_type]
|
|
511
532
|
)
|
|
512
533
|
|
|
@@ -531,6 +552,54 @@ class MetadataView(QWidget):
|
|
|
531
552
|
if not imported_data:
|
|
532
553
|
QMessageBox.warning(self, "Import Failed", "Failed to parse import file.")
|
|
533
554
|
return
|
|
555
|
+
|
|
556
|
+
# Handle Qdrant-specific requirements (similar to backup/restore)
|
|
557
|
+
from vector_inspector.core.connections.qdrant_connection import QdrantConnection
|
|
558
|
+
if isinstance(self.connection, QdrantConnection):
|
|
559
|
+
# Check if embeddings are missing and need to be generated
|
|
560
|
+
if not imported_data.get("embeddings"):
|
|
561
|
+
self.loading_dialog.setLabelText("Generating embeddings for Qdrant...")
|
|
562
|
+
QApplication.processEvents()
|
|
563
|
+
try:
|
|
564
|
+
from sentence_transformers import SentenceTransformer
|
|
565
|
+
model = SentenceTransformer("all-MiniLM-L6-v2")
|
|
566
|
+
documents = imported_data.get("documents", [])
|
|
567
|
+
imported_data["embeddings"] = model.encode(documents, show_progress_bar=False).tolist()
|
|
568
|
+
except Exception as e:
|
|
569
|
+
QMessageBox.warning(self, "Import Failed",
|
|
570
|
+
f"Qdrant requires embeddings. Failed to generate: {e}")
|
|
571
|
+
return
|
|
572
|
+
|
|
573
|
+
# Convert IDs to Qdrant-compatible format (integers or UUIDs)
|
|
574
|
+
# Store original IDs in metadata
|
|
575
|
+
original_ids = imported_data.get("ids", [])
|
|
576
|
+
qdrant_ids = []
|
|
577
|
+
metadatas = imported_data.get("metadatas", [])
|
|
578
|
+
|
|
579
|
+
for i, orig_id in enumerate(original_ids):
|
|
580
|
+
# Try to convert to integer, otherwise use index
|
|
581
|
+
try:
|
|
582
|
+
# If it's like "doc_123", extract the number
|
|
583
|
+
if isinstance(orig_id, str) and "_" in orig_id:
|
|
584
|
+
qdrant_id = int(orig_id.split("_")[-1])
|
|
585
|
+
else:
|
|
586
|
+
qdrant_id = int(orig_id)
|
|
587
|
+
except (ValueError, AttributeError):
|
|
588
|
+
# Use index as ID if can't convert
|
|
589
|
+
qdrant_id = i
|
|
590
|
+
|
|
591
|
+
qdrant_ids.append(qdrant_id)
|
|
592
|
+
|
|
593
|
+
# Store original ID in metadata
|
|
594
|
+
if i < len(metadatas):
|
|
595
|
+
if metadatas[i] is None:
|
|
596
|
+
metadatas[i] = {}
|
|
597
|
+
metadatas[i]["original_id"] = orig_id
|
|
598
|
+
else:
|
|
599
|
+
metadatas.append({"original_id": orig_id})
|
|
600
|
+
|
|
601
|
+
imported_data["ids"] = qdrant_ids
|
|
602
|
+
imported_data["metadatas"] = metadatas
|
|
534
603
|
|
|
535
604
|
# Add items to collection
|
|
536
605
|
success = self.connection.add_items(
|
|
@@ -544,6 +613,10 @@ class MetadataView(QWidget):
|
|
|
544
613
|
self.loading_dialog.hide_loading()
|
|
545
614
|
|
|
546
615
|
if success:
|
|
616
|
+
# Save the directory for next time
|
|
617
|
+
from pathlib import Path
|
|
618
|
+
self.settings_service.set("last_import_export_dir", str(Path(file_path).parent))
|
|
619
|
+
|
|
547
620
|
QMessageBox.information(
|
|
548
621
|
self,
|
|
549
622
|
"Import Successful",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/core/connections/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/services/filter_service.py
RENAMED
|
File without changes
|
{vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/services/settings_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/components/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/components/item_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/connection_view.py
RENAMED
|
File without changes
|
{vector_inspector-0.2.2 → vector_inspector-0.2.4}/src/vector_inspector/ui/views/search_view.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|