Skip to content

Commit 2934aad

Browse files
authored
Merge pull request #145 from weaviate/improve-batch-logic
Improve batch logic
2 parents 5a02cd4 + c30f720 commit 2934aad

4 files changed

Lines changed: 527 additions & 382 deletions

File tree

weaviate_cli/commands/create.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
CreateDataDefaults,
2727
CreateRoleDefaults,
2828
PERMISSION_HELP_STRING,
29+
MAX_WORKERS,
2930
)
3031

3132

@@ -89,7 +90,7 @@ def create() -> None:
8990
@click.option(
9091
"--training_limit",
9192
default=CreateCollectionDefaults.training_limit,
92-
help="Training limit for PQ and SQ (default: 10000).",
93+
help=f"Training limit for PQ and SQ (default: {CreateCollectionDefaults.training_limit}).",
9394
)
9495
@click.option(
9596
"--multitenant", is_flag=True, help="Enable multitenancy (default: False)."
@@ -228,7 +229,7 @@ def create_collection_cli(
228229
@click.option(
229230
"--number_tenants",
230231
default=CreateTenantsDefaults.number_tenants,
231-
help="Number of tenants to create (default: 100).",
232+
help=f"Number of tenants to create (default: {CreateTenantsDefaults.number_tenants}).",
232233
)
233234
@click.option(
234235
"--tenant_batch_size",
@@ -336,7 +337,8 @@ def create_backup_cli(ctx, backend, backup_id, include, exclude, wait, cpu_for_b
336337
@click.option(
337338
"--limit",
338339
default=CreateDataDefaults.limit,
339-
help="Number of objects to import (default: 1000).",
340+
help=f"Number of objects to import (default: {CreateDataDefaults.limit}).",
341+
type=int,
340342
)
341343
@click.option(
342344
"--consistency_level",
@@ -390,6 +392,23 @@ def create_backup_cli(ctx, backend, backup_id, include, exclude, wait, cpu_for_b
390392
is_flag=True,
391393
help="Enable multi-vector (default: False).",
392394
)
395+
@click.option(
396+
"--dynamic_batch",
397+
is_flag=True,
398+
help="Enable dynamic batching (default: False).",
399+
)
400+
@click.option(
401+
"--batch_size",
402+
default=CreateDataDefaults.batch_size,
403+
help=f"Number of objects to ingest in each batch (default: {CreateDataDefaults.batch_size}).",
404+
type=int,
405+
)
406+
@click.option(
407+
"--concurrent_requests",
408+
default=MAX_WORKERS,
409+
type=int,
410+
help=f"Number of concurrent requests to send to the server (default: {MAX_WORKERS}).",
411+
)
393412
@click.pass_context
394413
def create_data_cli(
395414
ctx,
@@ -406,6 +425,9 @@ def create_data_cli(
406425
wait_for_indexing,
407426
verbose,
408427
multi_vector,
428+
dynamic_batch,
429+
batch_size,
430+
concurrent_requests,
409431
):
410432
"""Ingest data into a collection in Weaviate."""
411433

@@ -423,6 +445,12 @@ def create_data_cli(
423445
click.echo("Error: --uuid has no effect unless --limit=1 is enabled.")
424446
sys.exit(1)
425447

448+
if dynamic_batch and not randomize:
449+
click.echo(
450+
"Error: --dynamic_batch has no effect unless --randomize is enabled."
451+
)
452+
sys.exit(1)
453+
426454
client: Optional[WeaviateClient] = None
427455
try:
428456
client = get_client_from_context(ctx)
@@ -442,6 +470,9 @@ def create_data_cli(
442470
wait_for_indexing=wait_for_indexing,
443471
verbose=verbose,
444472
multi_vector=multi_vector,
473+
dynamic_batch=dynamic_batch,
474+
batch_size=batch_size,
475+
concurrent_requests=concurrent_requests,
445476
)
446477
except Exception as e:
447478
click.echo(f"Error: {e}")

weaviate_cli/defaults.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from dataclasses import dataclass, field
2+
import multiprocessing
23
from typing import Optional, List, Dict
34

45

@@ -50,6 +51,14 @@
5051
QUERY_MAXIMUM_RESULTS = 10000
5152
MAX_OBJECTS_PER_BATCH = 5000
5253

54+
try:
55+
_CPU_COUNT = multiprocessing.cpu_count()
56+
except (NotImplementedError, OSError):
57+
_CPU_COUNT = None
58+
# Fallback to 1 worker if CPU count is unavailable or invalid
59+
_SAFE_CPU_COUNT = _CPU_COUNT if isinstance(_CPU_COUNT, int) and _CPU_COUNT > 0 else 1
60+
MAX_WORKERS = min(32, _SAFE_CPU_COUNT + 4)
61+
5362

5463
@dataclass
5564
class CreateCollectionDefaults:
@@ -102,6 +111,8 @@ class CreateDataDefaults:
102111
wait_for_indexing: bool = False
103112
verbose: bool = False
104113
multi_vector: bool = False
114+
batch_size: int = 1000
115+
dynamic_batch: bool = False
105116

106117

107118
@dataclass

weaviate_cli/managers/config_manager.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from weaviate.exceptions import WeaviateGRPCUnavailableError
1010
from pathlib import Path
1111
from typing import Dict, Optional, Union
12+
from weaviate.config import AdditionalConfig, Timeout as WeaviateTimeout
1213

1314

1415
class ConfigManager:
@@ -107,6 +108,9 @@ def _create_client(
107108
) -> Union[weaviate.WeaviateClient, weaviate.WeaviateAsyncClient]:
108109
"""Internal method to create client based on async flag"""
109110
auth_config: Optional[weaviate.auth.AuthCredentials] = None
111+
additional_config: Optional[AdditionalConfig] = (
112+
self.__additional_config_if_slow()
113+
)
110114

111115
if "auth" in self.config:
112116
if self.config["auth"].get("type") == "user":
@@ -133,6 +137,7 @@ def _create_client(
133137
grpc_port=self.config["grpc_port"],
134138
auth_credentials=auth_config,
135139
headers=headers,
140+
additional_config=additional_config,
136141
)
137142
if async_client:
138143
return weaviate.use_async_with_local(**common_kwargs)
@@ -144,6 +149,7 @@ def _create_client(
144149
cluster_url=self.config["host"],
145150
auth_credentials=auth_config,
146151
headers=headers,
152+
additional_config=additional_config,
147153
)
148154
if async_client:
149155
try:
@@ -189,6 +195,7 @@ def _create_client(
189195
grpc_port=grpc_port,
190196
auth_credentials=auth_config,
191197
headers=headers,
198+
additional_config=additional_config,
192199
)
193200
else:
194201
common_kwargs = dict(
@@ -200,8 +207,25 @@ def _create_client(
200207
grpc_port=self.config["grpc_port"],
201208
auth_credentials=auth_config,
202209
headers=headers,
210+
additional_config=additional_config,
203211
)
204212

205213
if async_client:
206214
return weaviate.use_async_with_custom(**common_kwargs)
207215
return weaviate.connect_to_custom(**common_kwargs)
216+
217+
def __additional_config_if_slow(self) -> Optional[AdditionalConfig]:
218+
"""Return AdditionalConfig with doubled timeouts when SLOW_CONNECTION is set."""
219+
env_flag = os.getenv("SLOW_CONNECTION")
220+
if not env_flag:
221+
return None
222+
if str(env_flag).strip().lower() not in {"1", "true", "yes", "on"}:
223+
return None
224+
defaults = AdditionalConfig().timeout
225+
return AdditionalConfig(
226+
timeout=WeaviateTimeout(
227+
query=defaults.query * 2,
228+
insert=defaults.insert * 2,
229+
init=defaults.init * 2,
230+
)
231+
)

0 commit comments

Comments
 (0)