anywidget-vector 0.2.8__tar.gz → 0.3.0__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.
- anywidget_vector-0.3.0/CHANGELOG.md +109 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/PKG-INFO +3 -3
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/examples/fashion-mnist-parallel-coords-6d.py +52 -28
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/pyproject.toml +3 -3
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/ui/__init__.py +35 -4
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/ui/canvas.js +12 -4
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/ui/settings.js +2 -1
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/ui/sidebar.js +122 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/ui/styles.css +18 -13
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/widget.py +1 -1
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/uv.lock +3 -3
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/.github/workflows/ci.yml +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/.github/workflows/pypi.yml +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/.gitignore +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/.python-version +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/LICENSE +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/README.md +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/assets/demo.png +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/examples/demo.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/examples/test_add_numpy.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/examples/test_projection.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/chroma/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/chroma/client.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/chroma/converter.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/browser.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/client.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/converter.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/embed.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/lancedb/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/lancedb/client.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/lancedb/converter.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/pinecone/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/pinecone/client.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/pinecone/converter.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/qdrant/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/qdrant/client.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/qdrant/converter.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/weaviate/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/weaviate/client.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/weaviate/converter.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/demo.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/py.typed +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/static/icons.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/ui/constants.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/ui/properties.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/ui/toolbar.js +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/tests/__init__.py +0 -0
- {anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/tests/test_widget.py +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.0 (2026-03-16)
|
|
4
|
+
|
|
5
|
+
### New Features
|
|
6
|
+
|
|
7
|
+
- **Distance metrics sidebar**: Distance section with metric selector (euclidean, cosine, manhattan, dot product), configurable k-neighbors (0-50), and live nearest-neighbor display for the selected point
|
|
8
|
+
- **Dimension mapping display**: Sidebar now shows active visual mapping fields: color field, size range, shape field and unique shape count
|
|
9
|
+
|
|
10
|
+
### Improvements
|
|
11
|
+
|
|
12
|
+
- Improved sidebar styling and layout
|
|
13
|
+
|
|
14
|
+
## 0.2.8 (2026-03-15)
|
|
15
|
+
|
|
16
|
+
### New Features
|
|
17
|
+
|
|
18
|
+
- **6D parallel coordinates example**: Fashion-MNIST demo with PCA across 6+ dimensions, interactive axis mapping, and shape mapping to categorical labels
|
|
19
|
+
|
|
20
|
+
## 0.2.7 (2026-03-15)
|
|
21
|
+
|
|
22
|
+
### New Features
|
|
23
|
+
|
|
24
|
+
- **Dark/light mode toggle**: `dark_mode` trait with real-time CSS color scheme switching and theme-aware styling across all panels
|
|
25
|
+
|
|
26
|
+
## 0.2.6 (2026-03-15)
|
|
27
|
+
|
|
28
|
+
### New Features
|
|
29
|
+
|
|
30
|
+
- **NumPy array support**: `add_numpy()` method for adding points from arrays with automatic PCA projection for high-dimensional data (D > 3)
|
|
31
|
+
- **Dimensionality reduction**: `project()` method with PCA, t-SNE and UMAP support; `set_vectors()` for storing high-dimensional vectors separately
|
|
32
|
+
- **Example scripts**: Projection demo and numpy integration examples
|
|
33
|
+
|
|
34
|
+
### Improvements
|
|
35
|
+
|
|
36
|
+
- High-dimensional vector storage without syncing to JavaScript
|
|
37
|
+
- Coordinate normalization after projection
|
|
38
|
+
- Added demo screenshot to README
|
|
39
|
+
|
|
40
|
+
## 0.2.5 (2026-03-04)
|
|
41
|
+
|
|
42
|
+
### Bug Fixes
|
|
43
|
+
|
|
44
|
+
- Fixed lasso selection stability issues
|
|
45
|
+
- Removed problematic custom traitlets implementation
|
|
46
|
+
|
|
47
|
+
### Improvements
|
|
48
|
+
|
|
49
|
+
- Added keyboard shortcuts: F to fit view, Escape to clear selection
|
|
50
|
+
- Better visual feedback for selection modes
|
|
51
|
+
- Cleaner toolbar layout with integrated mode controls
|
|
52
|
+
|
|
53
|
+
## 0.2.4 (2026-03-02)
|
|
54
|
+
|
|
55
|
+
### New Features
|
|
56
|
+
|
|
57
|
+
- **Zoom and pan controls**: Zoom in, zoom out and fit-to-view buttons in the toolbar
|
|
58
|
+
- **Box selection mode**: New selection mode alongside click and multi-select, with visual feedback during selection
|
|
59
|
+
- **HTML export**: `to_html()` and `save_html()` methods for self-contained HTML output with embedded data and Three.js
|
|
60
|
+
|
|
61
|
+
### Improvements
|
|
62
|
+
|
|
63
|
+
- Improved camera fitting algorithm for better initial view framing
|
|
64
|
+
- Updated README with comprehensive usage examples
|
|
65
|
+
- Updated dependencies
|
|
66
|
+
|
|
67
|
+
## 0.2.3 (2026-02-12)
|
|
68
|
+
|
|
69
|
+
### New Features
|
|
70
|
+
|
|
71
|
+
- **Sidebar explorer**: Three collapsible sections: collections browser, dimensions explorer (point count, dimensionality, axis ranges) and clusters explorer (grouped by color field with sizes)
|
|
72
|
+
- **Browser-side Grafeo backend**: JavaScript client for Grafeo server and WASM-embedded queries
|
|
73
|
+
- **Demo module**: Reference implementation showing various widget features
|
|
74
|
+
|
|
75
|
+
### Improvements
|
|
76
|
+
|
|
77
|
+
- Consistency pass across all backend modules
|
|
78
|
+
- Ruff configuration tuned for marimo compatibility
|
|
79
|
+
|
|
80
|
+
## 0.2.2 (2026-02-07)
|
|
81
|
+
|
|
82
|
+
### New Features
|
|
83
|
+
|
|
84
|
+
- **Streaming factory methods**: `from_numpy()`, `from_umap()` and `from_arrays()` constructors for various data formats
|
|
85
|
+
|
|
86
|
+
### Improvements
|
|
87
|
+
|
|
88
|
+
- Added Apache 2.0 license
|
|
89
|
+
- Expanded test suite with 194 additional test cases
|
|
90
|
+
- ESM bundle aggregation for widget JavaScript
|
|
91
|
+
|
|
92
|
+
## 0.2.1 (2026-02-03)
|
|
93
|
+
|
|
94
|
+
### New Features
|
|
95
|
+
|
|
96
|
+
- **Multi-backend architecture**: Six backends: Qdrant, Pinecone, Weaviate (browser-side REST), Chroma, LanceDB, Grafeo (Python-side)
|
|
97
|
+
- **Modular UI**: Separated rendering into canvas, settings, properties and toolbar components
|
|
98
|
+
- **Backend factory methods**: `from_qdrant()`, `from_pinecone()`, `from_weaviate()`, `from_chroma()`, `from_lancedb()`, `from_grafeo()`
|
|
99
|
+
- **Event system**: `on_click()`, `on_hover()` and `on_selection()` decorators with callback signatures
|
|
100
|
+
- **CI/CD**: GitHub Actions pipelines for testing and PyPI publishing
|
|
101
|
+
|
|
102
|
+
### Improvements
|
|
103
|
+
|
|
104
|
+
- Refactored monolithic widget into modular component architecture
|
|
105
|
+
- Added README with usage examples
|
|
106
|
+
|
|
107
|
+
## 0.1.0 (2026-02-03)
|
|
108
|
+
|
|
109
|
+
- Initial release: Three.js-based interactive 3D vector visualization with instanced rendering, six shape types, continuous and categorical color mapping, orbit controls, hover tooltips, axes/grid display and raycast-based selection
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: anywidget-vector
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Interactive 3D vector visualization with query UI for vector databases
|
|
5
5
|
Project-URL: Homepage, https://grafeo.dev/
|
|
6
6
|
Project-URL: Repository, https://github.com/GrafeoDB/anywidget-vector
|
|
@@ -33,10 +33,10 @@ Requires-Dist: chromadb>=0.4; extra == 'chroma'
|
|
|
33
33
|
Provides-Extra: demo
|
|
34
34
|
Provides-Extra: dev
|
|
35
35
|
Requires-Dist: marimo>=0.20; extra == 'dev'
|
|
36
|
-
Requires-Dist: prek>=0.3
|
|
36
|
+
Requires-Dist: prek>=0.3; extra == 'dev'
|
|
37
37
|
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
38
38
|
Requires-Dist: ruff>=0.15; extra == 'dev'
|
|
39
|
-
Requires-Dist: ty>=0.0
|
|
39
|
+
Requires-Dist: ty>=0.0; extra == 'dev'
|
|
40
40
|
Provides-Extra: embed
|
|
41
41
|
Provides-Extra: grafeo
|
|
42
42
|
Requires-Dist: grafeo>=0.5; extra == 'grafeo'
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/examples/fashion-mnist-parallel-coords-6d.py
RENAMED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
# Based on the Fashion MNIST Parallel Coordinates notebook by the marimo team:
|
|
2
|
+
# https://github.com/marimo-team/gallery-examples/blob/main/notebooks/wigglystuff/fashion-mnist-parallel-coords.py
|
|
3
|
+
#
|
|
4
|
+
# Extended with anywidget-vector 3D scatter view and 6D dimension mapping.
|
|
5
|
+
#
|
|
1
6
|
# /// script
|
|
2
7
|
# requires-python = ">=3.12"
|
|
3
8
|
# dependencies = [
|
|
@@ -14,7 +19,7 @@
|
|
|
14
19
|
|
|
15
20
|
import marimo
|
|
16
21
|
|
|
17
|
-
__generated_with = "0.
|
|
22
|
+
__generated_with = "0.19.7"
|
|
18
23
|
app = marimo.App(width="full")
|
|
19
24
|
|
|
20
25
|
|
|
@@ -36,7 +41,7 @@ def _():
|
|
|
36
41
|
@app.cell(hide_code=True)
|
|
37
42
|
def _(mo):
|
|
38
43
|
mo.md(r"""
|
|
39
|
-
# Fashion MNIST: Parallel Coordinates +
|
|
44
|
+
# Fashion MNIST: Parallel Coordinates + 6D Vector View
|
|
40
45
|
|
|
41
46
|
Brush the parallel coordinates axes to filter. The 3D scatter updates in real time.
|
|
42
47
|
Use the dropdowns to map PCA dimensions to visual channels.
|
|
@@ -62,18 +67,9 @@ def _(fetch_openml, np):
|
|
|
62
67
|
8: "Bag",
|
|
63
68
|
9: "Ankle boot",
|
|
64
69
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"Pullover": "#10b981",
|
|
69
|
-
"Dress": "#ef4444",
|
|
70
|
-
"Coat": "#8b5cf6",
|
|
71
|
-
"Sandal": "#06b6d4",
|
|
72
|
-
"Shirt": "#f97316",
|
|
73
|
-
"Sneaker": "#84cc16",
|
|
74
|
-
"Bag": "#ec4899",
|
|
75
|
-
"Ankle boot": "#14b8a6",
|
|
76
|
-
}
|
|
70
|
+
# d3 schemeCategory10, assigned alphabetically to match wigglystuff
|
|
71
|
+
_d3 = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"]
|
|
72
|
+
LABEL_COLORS = {_name: _d3[_i] for _i, _name in enumerate(sorted(label_names.values()))}
|
|
77
73
|
SHAPE_NAMES = ["sphere", "cube", "cone", "octahedron", "cylinder", "tetrahedron"]
|
|
78
74
|
return LABEL_COLORS, SHAPE_NAMES, images, label_names, labels
|
|
79
75
|
|
|
@@ -110,8 +106,8 @@ def _(
|
|
|
110
106
|
|
|
111
107
|
|
|
112
108
|
@app.cell
|
|
113
|
-
def _(ParallelCoordinates, df, mo):
|
|
114
|
-
widget = mo.ui.anywidget(ParallelCoordinates(df, color_by="label"))
|
|
109
|
+
def _(LABEL_COLORS, ParallelCoordinates, df, mo):
|
|
110
|
+
widget = mo.ui.anywidget(ParallelCoordinates(df, color_by="label", color_map=LABEL_COLORS))
|
|
115
111
|
widget
|
|
116
112
|
return (widget,)
|
|
117
113
|
|
|
@@ -122,9 +118,9 @@ def _(mo, n_components_slider):
|
|
|
122
118
|
x_dim = mo.ui.dropdown(options=pcs, value="PC1", label="X")
|
|
123
119
|
y_dim = mo.ui.dropdown(options=pcs, value="PC2", label="Y")
|
|
124
120
|
z_dim = mo.ui.dropdown(options=pcs, value="PC3", label="Z")
|
|
125
|
-
size_dim = mo.ui.dropdown(options=["none", *pcs], value="
|
|
121
|
+
size_dim = mo.ui.dropdown(options=["none", *pcs], value="PC4", label="Size")
|
|
126
122
|
color_dim = mo.ui.dropdown(options=["label", *pcs], value="label", label="Color")
|
|
127
|
-
shape_dim = mo.ui.dropdown(options=["label", "none"], value="
|
|
123
|
+
shape_dim = mo.ui.dropdown(options=["label", "none", *pcs], value="PC5", label="Shape")
|
|
128
124
|
mo.hstack([x_dim, y_dim, z_dim, size_dim, color_dim, shape_dim], gap=0.5)
|
|
129
125
|
return color_dim, shape_dim, size_dim, x_dim, y_dim, z_dim
|
|
130
126
|
|
|
@@ -140,6 +136,7 @@ def _(
|
|
|
140
136
|
label_names,
|
|
141
137
|
labels,
|
|
142
138
|
mo,
|
|
139
|
+
np,
|
|
143
140
|
shape_dim,
|
|
144
141
|
size_dim,
|
|
145
142
|
x_dim,
|
|
@@ -152,8 +149,23 @@ def _(
|
|
|
152
149
|
_xi, _yi, _zi = _pc(x_dim.value), _pc(y_dim.value), _pc(z_dim.value)
|
|
153
150
|
_color_pc = None if color_dim.value == "label" else _pc(color_dim.value)
|
|
154
151
|
_size_pc = None if size_dim.value == "none" else _pc(size_dim.value)
|
|
152
|
+
_shape_mode = shape_dim.value # "label", "none", or a PC name
|
|
153
|
+
|
|
154
|
+
# Shape mapping: label-based or PC-based (binned into 6 shape buckets)
|
|
155
155
|
_unique_labels = sorted(set(label_names.values()))
|
|
156
156
|
_shape_map = {_n: SHAPE_NAMES[_j % len(SHAPE_NAMES)] for _j, _n in enumerate(_unique_labels)}
|
|
157
|
+
_shape_bins = None
|
|
158
|
+
if _shape_mode not in ("label", "none"):
|
|
159
|
+
_shape_col = components[:, _pc(_shape_mode)]
|
|
160
|
+
_quantiles = np.percentile(_shape_col, np.linspace(0, 100, len(SHAPE_NAMES) + 1))
|
|
161
|
+
_shape_bins = list(zip(_quantiles[:-1], _quantiles[1:], SHAPE_NAMES, strict=False))
|
|
162
|
+
_shape_map = {_s: _s for _s in SHAPE_NAMES}
|
|
163
|
+
|
|
164
|
+
def _get_shape_bin(_val):
|
|
165
|
+
for _lo, _hi, _s in _shape_bins:
|
|
166
|
+
if _val <= _hi:
|
|
167
|
+
return _s
|
|
168
|
+
return SHAPE_NAMES[-1]
|
|
157
169
|
|
|
158
170
|
vs_points = []
|
|
159
171
|
for _i in range(len(components)):
|
|
@@ -171,8 +183,10 @@ def _(
|
|
|
171
183
|
_p["color_val"] = float(components[_i, _color_pc])
|
|
172
184
|
if _size_pc is not None:
|
|
173
185
|
_p["size_val"] = float(components[_i, _size_pc])
|
|
174
|
-
if
|
|
186
|
+
if _shape_mode == "label":
|
|
175
187
|
_p["shape_cat"] = _name
|
|
188
|
+
elif _shape_bins is not None:
|
|
189
|
+
_p["shape_cat"] = _get_shape_bin(components[_i, _pc(_shape_mode)])
|
|
176
190
|
vs_points.append(_p)
|
|
177
191
|
|
|
178
192
|
_vs_kwargs = {
|
|
@@ -183,17 +197,15 @@ def _(
|
|
|
183
197
|
_vs_kwargs["color_scale"] = "viridis"
|
|
184
198
|
if _size_pc is not None:
|
|
185
199
|
_vs_kwargs["size_field"] = "size_val"
|
|
186
|
-
_vs_kwargs["size_range"] = [0.01, 0.
|
|
187
|
-
if
|
|
200
|
+
_vs_kwargs["size_range"] = [0.01, 0.03]
|
|
201
|
+
if _shape_mode != "none":
|
|
188
202
|
_vs_kwargs["shape_field"] = "shape_cat"
|
|
189
203
|
_vs_kwargs["shape_map"] = _shape_map
|
|
190
204
|
|
|
191
205
|
vs_widget = VectorSpace(
|
|
192
206
|
points=vs_points,
|
|
193
|
-
width=
|
|
207
|
+
width=1600,
|
|
194
208
|
height=500,
|
|
195
|
-
dark_mode=False,
|
|
196
|
-
background="#fafafa",
|
|
197
209
|
show_toolbar=True,
|
|
198
210
|
show_settings=True,
|
|
199
211
|
show_properties=False,
|
|
@@ -201,7 +213,7 @@ def _(
|
|
|
201
213
|
)
|
|
202
214
|
vs = mo.ui.anywidget(vs_widget)
|
|
203
215
|
vs
|
|
204
|
-
return
|
|
216
|
+
return vs_points, vs_widget
|
|
205
217
|
|
|
206
218
|
|
|
207
219
|
@app.cell
|
|
@@ -225,17 +237,29 @@ def _(LABEL_COLORS, color_dim, mo, vs_points, vs_widget, widget):
|
|
|
225
237
|
|
|
226
238
|
|
|
227
239
|
@app.cell
|
|
228
|
-
def _(idx, images, label_names, labels, np, plt, widget):
|
|
240
|
+
def _(LABEL_COLORS, idx, images, label_names, labels, np, plt, vs_widget, widget):
|
|
229
241
|
_filtered = widget.widget.filtered_indices
|
|
230
242
|
_sample_idx = np.array(_filtered[:10]) if len(_filtered) >= 10 else np.array(_filtered)
|
|
231
243
|
|
|
232
|
-
|
|
244
|
+
# Which points are selected in the 3D view?
|
|
245
|
+
_selected_ids = set(vs_widget.selected_points or [])
|
|
246
|
+
|
|
247
|
+
_fig, _axes = plt.subplots(1, len(_sample_idx), figsize=(2 * len(_sample_idx), 2.4))
|
|
233
248
|
if len(_sample_idx) == 1:
|
|
234
249
|
_axes = [_axes]
|
|
235
250
|
for _ax, _si in zip(_axes, _sample_idx, strict=False):
|
|
251
|
+
_name = label_names[labels[idx[_si]]]
|
|
236
252
|
_ax.imshow(images[idx[_si]].reshape(28, 28), cmap="gray")
|
|
237
|
-
_ax.set_title(
|
|
253
|
+
_ax.set_title(_name, fontsize=9)
|
|
238
254
|
_ax.axis("off")
|
|
255
|
+
# Highlight if selected in 3D view
|
|
256
|
+
if f"p_{_si}" in _selected_ids:
|
|
257
|
+
_color = LABEL_COLORS.get(_name, "#0880ea")
|
|
258
|
+
for _spine in _ax.spines.values():
|
|
259
|
+
_spine.set_visible(True)
|
|
260
|
+
_spine.set_color(_color)
|
|
261
|
+
_spine.set_linewidth(3)
|
|
262
|
+
_ax.set_title(_name, fontsize=9, fontweight="bold", color=_color)
|
|
239
263
|
plt.tight_layout()
|
|
240
264
|
_fig
|
|
241
265
|
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "anywidget-vector"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Interactive 3D vector visualization with query UI for vector databases"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -26,10 +26,10 @@ dependencies = [
|
|
|
26
26
|
|
|
27
27
|
[project.optional-dependencies]
|
|
28
28
|
dev = [
|
|
29
|
-
"prek>=0.3
|
|
29
|
+
"prek>=0.3",
|
|
30
30
|
"pytest>=9.0.2",
|
|
31
31
|
"ruff>=0.15",
|
|
32
|
-
"ty>=0.0
|
|
32
|
+
"ty>=0.0",
|
|
33
33
|
"marimo>=0.20",
|
|
34
34
|
]
|
|
35
35
|
pandas = ["pandas>=2.0"]
|
|
@@ -122,16 +122,47 @@ async function executeBackendQuery(model) {{
|
|
|
122
122
|
function render({{ model, el }}) {{
|
|
123
123
|
const wrapper = document.createElement("div");
|
|
124
124
|
wrapper.className = "avs-wrapper";
|
|
125
|
-
if (model.get("dark_mode")) wrapper.classList.add("avs-dark");
|
|
126
125
|
wrapper.style.width = model.get("width") + "px";
|
|
127
126
|
wrapper.style.height = model.get("height") + "px";
|
|
128
127
|
el.appendChild(wrapper);
|
|
129
128
|
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
// Auto-detect host theme (marimo uses Tailwind class="dark" on <html>)
|
|
130
|
+
function detectHostDark() {{
|
|
131
|
+
const html = document.documentElement;
|
|
132
|
+
if (html.classList.contains("dark")) return true;
|
|
133
|
+
if (html.dataset.theme === "dark") return true;
|
|
134
|
+
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) return true;
|
|
135
|
+
return false;
|
|
136
|
+
}}
|
|
137
|
+
|
|
138
|
+
function applyTheme(dark) {{
|
|
132
139
|
wrapper.classList.toggle("avs-dark", dark);
|
|
133
|
-
model.set("background", dark ? "#
|
|
140
|
+
model.set("background", dark ? "#181c1a" : "#ffffff");
|
|
134
141
|
model.save_changes();
|
|
142
|
+
}}
|
|
143
|
+
|
|
144
|
+
// Detect if we're inside a themed host (marimo, jupyter, etc.)
|
|
145
|
+
const hasHostTheme = !!el.getRootNode()?.host?.tagName?.startsWith("MARIMO-");
|
|
146
|
+
if (hasHostTheme) {{
|
|
147
|
+
wrapper.classList.add("avs-auto-theme");
|
|
148
|
+
model.set("dark_mode", detectHostDark());
|
|
149
|
+
applyTheme(detectHostDark());
|
|
150
|
+
// Watch host for live theme changes
|
|
151
|
+
const themeObserver = new MutationObserver(() => {{
|
|
152
|
+
const dark = detectHostDark();
|
|
153
|
+
if (model.get("dark_mode") !== dark) {{
|
|
154
|
+
model.set("dark_mode", dark);
|
|
155
|
+
applyTheme(dark);
|
|
156
|
+
}}
|
|
157
|
+
}});
|
|
158
|
+
themeObserver.observe(document.documentElement, {{ attributes: true, attributeFilter: ["class", "data-theme"] }});
|
|
159
|
+
}} else {{
|
|
160
|
+
applyTheme(model.get("dark_mode"));
|
|
161
|
+
}}
|
|
162
|
+
|
|
163
|
+
// Manual toggle from settings panel still works
|
|
164
|
+
model.on("change:dark_mode", () => {{
|
|
165
|
+
applyTheme(model.get("dark_mode"));
|
|
135
166
|
}});
|
|
136
167
|
|
|
137
168
|
let sidebar = null;
|
|
@@ -175,12 +175,20 @@ export function createCanvas(model, container, callbacks) {
|
|
|
175
175
|
const points = model.get("points") || [];
|
|
176
176
|
if (points.length === 0) return;
|
|
177
177
|
|
|
178
|
+
// Auto-scale point sizes relative to data extent
|
|
179
|
+
const box = new THREE.Box3();
|
|
180
|
+
points.forEach(p => box.expandByPoint(new THREE.Vector3(p.x ?? 0, p.y ?? 0, p.z ?? 0)));
|
|
181
|
+
const dataSize = box.getSize(new THREE.Vector3()).length() || 1;
|
|
182
|
+
const scaleFactor = dataSize / 10;
|
|
183
|
+
const rawRange = model.get("size_range") || [0.02, 0.06];
|
|
184
|
+
const sizeRange = [rawRange[0] * scaleFactor, rawRange[1] * scaleFactor];
|
|
185
|
+
|
|
178
186
|
const opts = {
|
|
179
187
|
colorField: model.get("color_field"),
|
|
180
188
|
colorScale: model.get("color_scale") || "viridis",
|
|
181
189
|
colorDomain: model.get("color_domain"),
|
|
182
190
|
sizeField: model.get("size_field"),
|
|
183
|
-
sizeRange:
|
|
191
|
+
sizeRange: sizeRange,
|
|
184
192
|
shapeField: model.get("shape_field"),
|
|
185
193
|
shapeMap: model.get("shape_map") || {},
|
|
186
194
|
};
|
|
@@ -460,7 +468,7 @@ export function createCanvas(model, container, callbacks) {
|
|
|
460
468
|
const size = box.getSize(new THREE.Vector3()).length();
|
|
461
469
|
const distance = size / (2 * Math.tan(Math.PI * camera.fov / 360));
|
|
462
470
|
controls.target.copy(center);
|
|
463
|
-
camera.position.copy(center.clone().add(new THREE.Vector3(0, 0, distance *
|
|
471
|
+
camera.position.copy(center.clone().add(new THREE.Vector3(0, 0, distance * 0.55)));
|
|
464
472
|
camera.near = Math.max(0.01, distance * 0.001);
|
|
465
473
|
camera.far = Math.max(1000, distance * 10);
|
|
466
474
|
camera.updateProjectionMatrix();
|
|
@@ -485,8 +493,8 @@ export function createCanvas(model, container, callbacks) {
|
|
|
485
493
|
zoomOutBtn.innerHTML = ICONS.zoomOut;
|
|
486
494
|
zoomOutBtn.title = "Zoom out";
|
|
487
495
|
zoomOutBtn.addEventListener("click", () => {
|
|
488
|
-
const
|
|
489
|
-
camera.position.add(
|
|
496
|
+
const offset = camera.position.clone().sub(controls.target);
|
|
497
|
+
camera.position.add(offset.multiplyScalar(0.3));
|
|
490
498
|
controls.update();
|
|
491
499
|
});
|
|
492
500
|
|
|
@@ -21,8 +21,9 @@ export function createSettingsPanel(model, callbacks) {
|
|
|
21
21
|
header.appendChild(closeBtn);
|
|
22
22
|
inner.appendChild(header);
|
|
23
23
|
|
|
24
|
-
// Dark mode toggle
|
|
24
|
+
// Dark mode toggle (hidden when host provides theme)
|
|
25
25
|
const themeGroup = createFormGroup("Theme");
|
|
26
|
+
themeGroup.classList.add("avs-theme-toggle");
|
|
26
27
|
const toggle = document.createElement("label");
|
|
27
28
|
toggle.className = "avs-toggle";
|
|
28
29
|
const checkbox = document.createElement("input");
|
|
@@ -114,6 +114,22 @@ export function createSidebar(model, callbacks) {
|
|
|
114
114
|
addStatRow(dimContent, "X range", rangeStr(xs));
|
|
115
115
|
addStatRow(dimContent, "Y range", rangeStr(ys));
|
|
116
116
|
addStatRow(dimContent, "Z range", rangeStr(zs));
|
|
117
|
+
|
|
118
|
+
// Visual mapping dimensions
|
|
119
|
+
const colorField = model.get("color_field");
|
|
120
|
+
const sizeField = model.get("size_field");
|
|
121
|
+
const shapeField = model.get("shape_field");
|
|
122
|
+
if (colorField) addStatRow(dimContent, "Color", colorField);
|
|
123
|
+
if (sizeField) {
|
|
124
|
+
const sizeRange = model.get("size_range") || [0.02, 0.1];
|
|
125
|
+
addStatRow(dimContent, "Size", sizeField + " [" + sizeRange[0] + "," + sizeRange[1] + "]");
|
|
126
|
+
}
|
|
127
|
+
if (shapeField) {
|
|
128
|
+
const shapeMap = model.get("shape_map") || {};
|
|
129
|
+
const shapes = Object.values(shapeMap);
|
|
130
|
+
const unique = [...new Set(shapes)];
|
|
131
|
+
addStatRow(dimContent, "Shape", shapeField + " (" + unique.length + " shapes)");
|
|
132
|
+
}
|
|
117
133
|
}
|
|
118
134
|
|
|
119
135
|
function updateClusters() {
|
|
@@ -159,6 +175,107 @@ export function createSidebar(model, callbacks) {
|
|
|
159
175
|
});
|
|
160
176
|
}
|
|
161
177
|
|
|
178
|
+
// === Distance Section ===
|
|
179
|
+
const distSection = document.createElement("div");
|
|
180
|
+
distSection.className = "avs-sidebar-section";
|
|
181
|
+
|
|
182
|
+
const distHeader = document.createElement("div");
|
|
183
|
+
distHeader.className = "avs-section-header";
|
|
184
|
+
distHeader.textContent = "Distance";
|
|
185
|
+
distSection.appendChild(distHeader);
|
|
186
|
+
|
|
187
|
+
const distContent = document.createElement("div");
|
|
188
|
+
distContent.className = "avs-dimension-content";
|
|
189
|
+
|
|
190
|
+
// Metric selector
|
|
191
|
+
const metricGroup = document.createElement("div");
|
|
192
|
+
metricGroup.className = "avs-form-group";
|
|
193
|
+
const metricLabel = document.createElement("label");
|
|
194
|
+
metricLabel.className = "avs-label";
|
|
195
|
+
metricLabel.textContent = "Metric";
|
|
196
|
+
metricGroup.appendChild(metricLabel);
|
|
197
|
+
const metricSelect = document.createElement("select");
|
|
198
|
+
metricSelect.className = "avs-select";
|
|
199
|
+
metricSelect.style.width = "100%";
|
|
200
|
+
["euclidean", "cosine", "manhattan", "dot_product"].forEach(m => {
|
|
201
|
+
const opt = document.createElement("option");
|
|
202
|
+
opt.value = m;
|
|
203
|
+
opt.textContent = m;
|
|
204
|
+
opt.selected = m === (model.get("distance_metric") || "euclidean");
|
|
205
|
+
metricSelect.appendChild(opt);
|
|
206
|
+
});
|
|
207
|
+
metricSelect.addEventListener("change", () => {
|
|
208
|
+
model.set("distance_metric", metricSelect.value);
|
|
209
|
+
model.save_changes();
|
|
210
|
+
});
|
|
211
|
+
metricGroup.appendChild(metricSelect);
|
|
212
|
+
distContent.appendChild(metricGroup);
|
|
213
|
+
|
|
214
|
+
// K neighbors
|
|
215
|
+
const kGroup = document.createElement("div");
|
|
216
|
+
kGroup.className = "avs-form-group";
|
|
217
|
+
const kLabel = document.createElement("label");
|
|
218
|
+
kLabel.className = "avs-label";
|
|
219
|
+
kLabel.textContent = "K neighbors";
|
|
220
|
+
kGroup.appendChild(kLabel);
|
|
221
|
+
const kInput = document.createElement("input");
|
|
222
|
+
kInput.type = "number";
|
|
223
|
+
kInput.className = "avs-input";
|
|
224
|
+
kInput.min = "0";
|
|
225
|
+
kInput.max = "50";
|
|
226
|
+
kInput.value = model.get("k_neighbors") || 0;
|
|
227
|
+
kInput.addEventListener("input", () => {
|
|
228
|
+
const k = parseInt(kInput.value, 10) || 0;
|
|
229
|
+
model.set("k_neighbors", k);
|
|
230
|
+
model.set("show_connections", k > 0);
|
|
231
|
+
model.save_changes();
|
|
232
|
+
});
|
|
233
|
+
kGroup.appendChild(kInput);
|
|
234
|
+
distContent.appendChild(kGroup);
|
|
235
|
+
|
|
236
|
+
// Distance info (updates when points are selected)
|
|
237
|
+
const distInfo = document.createElement("div");
|
|
238
|
+
distInfo.className = "avs-note";
|
|
239
|
+
distInfo.textContent = "Select a point to see distances";
|
|
240
|
+
distContent.appendChild(distInfo);
|
|
241
|
+
|
|
242
|
+
distSection.appendChild(distContent);
|
|
243
|
+
inner.appendChild(distSection);
|
|
244
|
+
|
|
245
|
+
function updateDistanceInfo() {
|
|
246
|
+
const selected = model.get("selected_points") || [];
|
|
247
|
+
if (selected.length === 0) {
|
|
248
|
+
distInfo.textContent = "Select a point to see distances";
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const points = model.get("points") || [];
|
|
252
|
+
const ref = points.find(p => p.id === selected[0]);
|
|
253
|
+
if (!ref) return;
|
|
254
|
+
|
|
255
|
+
const metric = metricSelect.value;
|
|
256
|
+
const others = points.filter(p => p.id !== ref.id);
|
|
257
|
+
|
|
258
|
+
function dist(a, b) {
|
|
259
|
+
const dx = (a.x ?? 0) - (b.x ?? 0), dy = (a.y ?? 0) - (b.y ?? 0), dz = (a.z ?? 0) - (b.z ?? 0);
|
|
260
|
+
if (metric === "manhattan") return Math.abs(dx) + Math.abs(dy) + Math.abs(dz);
|
|
261
|
+
if (metric === "cosine") {
|
|
262
|
+
const dot = (a.x??0)*(b.x??0) + (a.y??0)*(b.y??0) + (a.z??0)*(b.z??0);
|
|
263
|
+
const ma = Math.sqrt((a.x??0)**2 + (a.y??0)**2 + (a.z??0)**2);
|
|
264
|
+
const mb = Math.sqrt((b.x??0)**2 + (b.y??0)**2 + (b.z??0)**2);
|
|
265
|
+
return (ma === 0 || mb === 0) ? 1 : 1 - dot / (ma * mb);
|
|
266
|
+
}
|
|
267
|
+
if (metric === "dot_product") return -((a.x??0)*(b.x??0) + (a.y??0)*(b.y??0) + (a.z??0)*(b.z??0));
|
|
268
|
+
return Math.sqrt(dx*dx + dy*dy + dz*dz);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const sorted = others.map(p => ({ id: p.id, label: p.label || p.id, d: dist(ref, p) }))
|
|
272
|
+
.sort((a, b) => a.d - b.d).slice(0, 5);
|
|
273
|
+
|
|
274
|
+
distInfo.innerHTML = "<strong>" + escapeHtml(ref.label || ref.id) + "</strong><br>" +
|
|
275
|
+
sorted.map(n => '<span class="avs-property-key">' + escapeHtml(n.label) +
|
|
276
|
+
'</span> <span class="avs-property-value">' + n.d.toFixed(2) + "</span>").join("<br>");
|
|
277
|
+
}
|
|
278
|
+
|
|
162
279
|
// === Event Bindings ===
|
|
163
280
|
model.on("change:points", () => {
|
|
164
281
|
updateDimensions();
|
|
@@ -167,6 +284,11 @@ export function createSidebar(model, callbacks) {
|
|
|
167
284
|
model.on("change:color_field", updateClusters);
|
|
168
285
|
model.on("change:backend_config", updateCollections);
|
|
169
286
|
model.on("change:backend", updateCollections);
|
|
287
|
+
model.on("change:selected_points", updateDistanceInfo);
|
|
288
|
+
model.on("change:distance_metric", () => {
|
|
289
|
+
metricSelect.value = model.get("distance_metric") || "euclidean";
|
|
290
|
+
updateDistanceInfo();
|
|
291
|
+
});
|
|
170
292
|
|
|
171
293
|
// Initial render
|
|
172
294
|
updateCollections();
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/* === CSS Variables === */
|
|
2
2
|
|
|
3
|
-
/* Light mode (default) */
|
|
3
|
+
/* Light mode (default, matches marimo light) */
|
|
4
4
|
.avs-wrapper {
|
|
5
5
|
--avs-bg: #ffffff;
|
|
6
6
|
--avs-surface: #f8f9fa;
|
|
7
|
-
--avs-border: #
|
|
8
|
-
--avs-text: #
|
|
7
|
+
--avs-border: #e2e8f0;
|
|
8
|
+
--avs-text: #0f172a;
|
|
9
9
|
--avs-text-muted: #6b7280;
|
|
10
|
-
--avs-primary: #
|
|
11
|
-
--avs-primary-hover: #
|
|
10
|
+
--avs-primary: #0880ea;
|
|
11
|
+
--avs-primary-hover: #0670d0;
|
|
12
12
|
--avs-success: #10b981;
|
|
13
13
|
--avs-warning: #f59e0b;
|
|
14
14
|
--avs-error: #ef4444;
|
|
@@ -23,15 +23,15 @@
|
|
|
23
23
|
flex-direction: column;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/* Dark mode */
|
|
26
|
+
/* Dark mode (matches marimo dark) */
|
|
27
27
|
.avs-wrapper.avs-dark {
|
|
28
|
-
--avs-bg: #
|
|
29
|
-
--avs-surface: #
|
|
30
|
-
--avs-border: #
|
|
31
|
-
--avs-text: #
|
|
32
|
-
--avs-text-muted: #
|
|
33
|
-
--avs-primary: #
|
|
34
|
-
--avs-primary-hover: #
|
|
28
|
+
--avs-bg: #181c1a;
|
|
29
|
+
--avs-surface: #252927;
|
|
30
|
+
--avs-border: #3b403e;
|
|
31
|
+
--avs-text: #eceeed;
|
|
32
|
+
--avs-text-muted: #9ca3af;
|
|
33
|
+
--avs-primary: #28879f;
|
|
34
|
+
--avs-primary-hover: #1d5b6a;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/* === Main Layout === */
|
|
@@ -601,3 +601,8 @@
|
|
|
601
601
|
font-size: 13px;
|
|
602
602
|
color: var(--avs-text);
|
|
603
603
|
}
|
|
604
|
+
|
|
605
|
+
/* Hide dark mode toggle when host provides theme */
|
|
606
|
+
.avs-wrapper.avs-auto-theme .avs-theme-toggle {
|
|
607
|
+
display: none;
|
|
608
|
+
}
|
|
@@ -54,7 +54,7 @@ class VectorSpace(anywidget.AnyWidget):
|
|
|
54
54
|
|
|
55
55
|
# === Size Mapping ===
|
|
56
56
|
size_field = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
|
|
57
|
-
size_range = traitlets.List(default_value=[0.02, 0.
|
|
57
|
+
size_range = traitlets.List(default_value=[0.02, 0.06]).tag(sync=True)
|
|
58
58
|
|
|
59
59
|
# === Shape Mapping ===
|
|
60
60
|
shape_field = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
|
|
@@ -50,7 +50,7 @@ wheels = [
|
|
|
50
50
|
|
|
51
51
|
[[package]]
|
|
52
52
|
name = "anywidget-vector"
|
|
53
|
-
version = "0.
|
|
53
|
+
version = "0.3.0"
|
|
54
54
|
source = { editable = "." }
|
|
55
55
|
dependencies = [
|
|
56
56
|
{ name = "anywidget" },
|
|
@@ -123,13 +123,13 @@ requires-dist = [
|
|
|
123
123
|
{ name = "pandas", marker = "extra == 'pandas'", specifier = ">=2.0" },
|
|
124
124
|
{ name = "pinecone-client", marker = "extra == 'all'", specifier = ">=6.0" },
|
|
125
125
|
{ name = "pinecone-client", marker = "extra == 'pinecone'", specifier = ">=3.0" },
|
|
126
|
-
{ name = "prek", marker = "extra == 'dev'", specifier = ">=0.3
|
|
126
|
+
{ name = "prek", marker = "extra == 'dev'", specifier = ">=0.3" },
|
|
127
127
|
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.2" },
|
|
128
128
|
{ name = "qdrant-client", marker = "extra == 'all'", specifier = ">=1" },
|
|
129
129
|
{ name = "qdrant-client", marker = "extra == 'qdrant'", specifier = ">=1.0" },
|
|
130
130
|
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15" },
|
|
131
131
|
{ name = "scikit-learn", marker = "extra == 'projection'", specifier = ">=1.3" },
|
|
132
|
-
{ name = "ty", marker = "extra == 'dev'", specifier = ">=0.0
|
|
132
|
+
{ name = "ty", marker = "extra == 'dev'", specifier = ">=0.0" },
|
|
133
133
|
{ name = "umap-learn", marker = "extra == 'projection'", specifier = ">=0.5" },
|
|
134
134
|
{ name = "weaviate-client", marker = "extra == 'all'", specifier = ">=4.20" },
|
|
135
135
|
{ name = "weaviate-client", marker = "extra == 'weaviate'", specifier = ">=4.0" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/chroma/__init__.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/chroma/client.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/chroma/converter.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/__init__.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/browser.js
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/client.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/converter.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/grafeo/embed.js
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/lancedb/__init__.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/lancedb/client.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/lancedb/converter.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/pinecone/__init__.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/pinecone/client.js
RENAMED
|
File without changes
|
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/qdrant/__init__.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/qdrant/client.js
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/qdrant/converter.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/weaviate/__init__.py
RENAMED
|
File without changes
|
{anywidget_vector-0.2.8 → anywidget_vector-0.3.0}/src/anywidget_vector/backends/weaviate/client.js
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
|
|
File without changes
|
|
File without changes
|