0
# Legacy Interface
1
2
The legacy interface (ngt.base) provides ctypes-based bindings for backward compatibility. While the modern interface (ngtpy) is recommended for new applications, the legacy interface remains useful for existing code and simpler use cases requiring manual memory management.
3
4
## Capabilities
5
6
### Index Management
7
8
Core index class using ctypes bindings for vector storage and search operations.
9
10
```python { .api }
11
class Index:
12
def __init__(self, path):
13
"""
14
Open existing index for read/write operations.
15
16
Args:
17
path (bytes): Path to index directory (must be bytes, not str)
18
"""
19
20
@staticmethod
21
def create(path, dimension, edge_size_for_creation=10, edge_size_for_search=40,
22
object_type="Float", distance_type="L2"):
23
"""
24
Create new empty index with specified parameters.
25
26
Args:
27
path (bytes): Index storage path (must be bytes, not str)
28
dimension (int): Vector dimensionality
29
edge_size_for_creation (int): Edges per node during creation (default: 10)
30
edge_size_for_search (int): Edges per node during search (default: 40)
31
object_type (str): Data type - "Float", "Integer" (1 byte unsigned) (default: "Float")
32
distance_type (str): Distance function - "L2", "L1", "Angle", "Hamming",
33
"Jaccard", "Cosine" (default: "L2")
34
35
Returns:
36
Index: New Index object
37
"""
38
```
39
40
### Vector Search
41
42
Search for nearest neighbors with simplified parameter control.
43
44
```python { .api }
45
class Index:
46
def search(self, query, k=20, epsilon=0.1):
47
"""
48
Search for k nearest neighbors.
49
50
Args:
51
query (array-like): Query vector
52
k (int): Number of nearest neighbors to return (default: 20)
53
epsilon (float): Search range expansion parameter (default: 0.1)
54
55
Returns:
56
list: List of ObjectDistance instances with id and distance attributes
57
"""
58
```
59
60
### Vector Insertion
61
62
Insert vectors using simplified insertion methods with automatic index building.
63
64
```python { .api }
65
class Index:
66
def insert_object(self, object):
67
"""
68
Insert single object without building index.
69
70
Args:
71
object (array-like): Vector to insert
72
73
Returns:
74
int: Object ID of inserted vector
75
"""
76
77
def insert(self, objects, num_threads=8):
78
"""
79
Insert multiple objects and build index.
80
81
Args:
82
objects (array-like): Array of vectors to insert
83
num_threads (int): Number of threads for insertion (default: 8)
84
85
Returns:
86
None
87
"""
88
89
def insert_blob(self, objects, num_threads=8):
90
"""
91
Insert multiple objects using blob method and build index.
92
93
Args:
94
objects (array-like): Array of vectors to insert
95
num_threads (int): Number of threads for insertion (default: 8)
96
97
Returns:
98
None
99
"""
100
101
def insert_from_tsv(self, path, num_threads=8, dlmt='\t'):
102
"""
103
Insert objects from TSV file and build index.
104
105
Args:
106
path (str): Path to TSV file containing vectors
107
num_threads (int): Number of threads for insertion (default: 8)
108
dlmt (str): Delimiter character (default: '\t')
109
110
Returns:
111
None
112
"""
113
```
114
115
### Index Building and Management
116
117
Build indexes and manage index persistence with simplified operations.
118
119
```python { .api }
120
class Index:
121
def build_index(self, num_threads=8):
122
"""
123
Build index for previously inserted objects.
124
125
Args:
126
num_threads (int): Number of threads for building (default: 8)
127
128
Returns:
129
None
130
"""
131
132
def save(self, path=None):
133
"""
134
Save index to disk.
135
136
Args:
137
path (str, optional): Save path, uses original path if None
138
139
Returns:
140
None
141
"""
142
```
143
144
### Object Management
145
146
Access and manage indexed objects with basic retrieval and removal operations.
147
148
```python { .api }
149
class Index:
150
def get_object(self, id):
151
"""
152
Retrieve object by ID.
153
154
Args:
155
id (int): Object identifier
156
157
Returns:
158
list: Vector as list of floats
159
"""
160
161
def remove(self, id):
162
"""
163
Remove object from index.
164
165
Args:
166
id (int): Object identifier to remove
167
168
Returns:
169
None
170
"""
171
```
172
173
### Result Structure
174
175
Data structure for search results containing object ID and distance information.
176
177
```python { .api }
178
class ObjectDistance:
179
"""
180
Search result structure containing object ID and distance.
181
182
Attributes:
183
id (int): Object identifier (c_uint)
184
distance (float): Distance value (c_float)
185
"""
186
id: int
187
distance: float
188
```
189
190
### Exception Classes
191
192
Exception classes for error handling in the legacy interface.
193
194
```python { .api }
195
class NativeError(Exception):
196
"""
197
Exception raised when underlying C library encounters errors.
198
199
This exception is raised for low-level library errors, memory issues,
200
or invalid operations on the native NGT library.
201
"""
202
203
class APIError(Exception):
204
"""
205
Exception raised for API usage errors.
206
207
This exception is raised for invalid API usage, incorrect parameters,
208
or operations that violate the API contract.
209
"""
210
```
211
212
## Usage Examples
213
214
### Basic Index Creation and Search
215
216
```python
217
from ngt import base as ngt
218
import random
219
220
# Create sample data
221
dim = 10
222
nb = 100
223
vectors = [[random.random() for _ in range(dim)] for _ in range(nb)]
224
query = vectors[0]
225
226
# Create index
227
ngt.Index.create("legacy_index", dim, distance_type="L2", object_type="Float")
228
229
# Open index and insert data
230
index = ngt.Index("legacy_index")
231
index.insert(vectors, num_threads=4)
232
index.save()
233
234
# Search for nearest neighbors
235
results = index.search(query, k=5, epsilon=0.1)
236
for i, result in enumerate(results):
237
print(f"Rank {i+1}: Object {result.id}, Distance {result.distance:.4f}")
238
vector = index.get_object(result.id)
239
print(f"Vector: {vector[:3]}...") # Show first 3 dimensions
240
```
241
242
### Individual Object Insertion
243
244
```python
245
from ngt import base as ngt
246
import random
247
248
# Create empty index
249
ngt.Index.create("incremental_legacy", 64, edge_size_for_creation=15)
250
index = ngt.Index("incremental_legacy")
251
252
# Insert objects one by one
253
object_ids = []
254
for i in range(50):
255
vector = [random.random() for _ in range(64)]
256
obj_id = index.insert_object(vector)
257
object_ids.append(obj_id)
258
print(f"Inserted object {obj_id}")
259
260
# Build index after insertions
261
index.build_index(num_threads=2)
262
index.save()
263
264
print(f"Index built with {len(object_ids)} objects")
265
```
266
267
### TSV File Import
268
269
```python
270
from ngt import base as ngt
271
272
# Create index for TSV import
273
ngt.Index.create("tsv_index", 128, distance_type="Cosine")
274
index = ngt.Index("tsv_index")
275
276
# Import vectors from TSV file
277
# File format: each line contains tab-separated vector components
278
index.insert_from_tsv("vectors.tsv", num_threads=8, dlmt='\t')
279
index.save()
280
281
# Search example
282
query = [0.5] * 128 # Example query vector
283
results = index.search(query, k=10, epsilon=0.05)
284
285
print(f"Found {len(results)} nearest neighbors")
286
for result in results:
287
print(f"Object {result.id}: distance {result.distance:.6f}")
288
```
289
290
### Error Handling
291
292
```python
293
from ngt import base as ngt
294
295
try:
296
# Attempt to open non-existent index
297
index = ngt.Index("nonexistent_index")
298
except ngt.NativeError as e:
299
print(f"Native library error: {e}")
300
except ngt.APIError as e:
301
print(f"API usage error: {e}")
302
303
try:
304
# Create index with invalid parameters
305
ngt.Index.create("test_index", -1) # Invalid dimension
306
except ngt.APIError as e:
307
print(f"Invalid parameters: {e}")
308
```
309
310
### Comparison with Modern Interface
311
312
```python
313
# Legacy interface example
314
from ngt import base as ngt_legacy
315
import ngtpy
316
317
# Legacy approach
318
ngt_legacy.Index.create("legacy_idx", 10, distance_type="L2")
319
legacy_index = ngt_legacy.Index("legacy_idx")
320
legacy_results = legacy_index.search(query, k=5, epsilon=0.1)
321
322
# Modern approach (equivalent)
323
ngtpy.create("modern_idx", 10, distance_type="L2")
324
modern_index = ngtpy.Index("modern_idx")
325
modern_results = modern_index.search(query, size=5, epsilon=0.1)
326
327
# Legacy results are ObjectDistance objects
328
for result in legacy_results:
329
print(f"Legacy: {result.id}, {result.distance}")
330
331
# Modern results are tuples
332
for obj_id, distance in modern_results:
333
print(f"Modern: {obj_id}, {distance}")
334
```