crewplus 0.2.28__tar.gz → 0.2.30__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.

Potentially problematic release.


This version of crewplus might be problematic. Click here for more details.

Files changed (22) hide show
  1. {crewplus-0.2.28 → crewplus-0.2.30}/PKG-INFO +1 -1
  2. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/services/model_load_balancer.py +32 -8
  3. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/vectorstores/milvus/vdb_service.py +29 -3
  4. {crewplus-0.2.28 → crewplus-0.2.30}/pyproject.toml +1 -1
  5. {crewplus-0.2.28 → crewplus-0.2.30}/LICENSE +0 -0
  6. {crewplus-0.2.28 → crewplus-0.2.30}/README.md +0 -0
  7. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/__init__.py +0 -0
  8. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/services/__init__.py +0 -0
  9. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/services/azure_chat_model.py +0 -0
  10. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/services/gemini_chat_model.py +0 -0
  11. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/services/init_services.py +0 -0
  12. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/services/tracing_manager.py +0 -0
  13. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/utils/__init__.py +0 -0
  14. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/utils/schema_action.py +0 -0
  15. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/utils/schema_document_updater.py +0 -0
  16. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/vectorstores/milvus/__init__.py +0 -0
  17. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/vectorstores/milvus/milvus_schema_manager.py +0 -0
  18. {crewplus-0.2.28 → crewplus-0.2.30}/crewplus/vectorstores/milvus/schema_milvus.py +0 -0
  19. {crewplus-0.2.28 → crewplus-0.2.30}/docs/GeminiChatModel.md +0 -0
  20. {crewplus-0.2.28 → crewplus-0.2.30}/docs/ModelLoadBalancer.md +0 -0
  21. {crewplus-0.2.28 → crewplus-0.2.30}/docs/VDBService.md +0 -0
  22. {crewplus-0.2.28 → crewplus-0.2.30}/docs/index.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: crewplus
3
- Version: 0.2.28
3
+ Version: 0.2.30
4
4
  Summary: Base services for CrewPlus AI applications
5
5
  Author-Email: Tim Liu <tim@opsmateai.com>
6
6
  License: MIT
@@ -76,21 +76,23 @@ class ModelLoadBalancer:
76
76
  self.logger.error(f"Failed to load model configuration: {e}", exc_info=True)
77
77
  raise RuntimeError(f"Failed to load model configuration: {e}")
78
78
 
79
- def get_model(self, provider: str = None, model_type: str = None, deployment_name: str = None):
79
+ def get_model(self, provider: str = None, model_type: str = None, deployment_name: str = None, with_metadata: bool = False, selection_strategy: str = 'random'):
80
80
  """
81
81
  Get a model instance.
82
82
 
83
83
  Can fetch a model in two ways:
84
84
  1. By its specific `deployment_name`.
85
- 2. By `provider` and `model_type`, which will select a model using round-robin.
85
+ 2. By `provider` and `model_type`, which will select a model using a specified strategy.
86
86
 
87
87
  Args:
88
88
  provider: The model provider (e.g., 'azure-openai', 'google-genai').
89
89
  model_type: The type of model (e.g., 'inference', 'embedding', 'embedding-large').
90
90
  deployment_name: The unique name for the model deployment.
91
+ with_metadata: If True, returns a tuple of (model, deployment_name).
92
+ selection_strategy: The selection strategy ('random', 'round_robin', or 'least_used'). Defaults to 'random'.
91
93
 
92
94
  Returns:
93
- An instantiated language model object.
95
+ An instantiated language model object, or a tuple if with_metadata is True.
94
96
 
95
97
  Raises:
96
98
  RuntimeError: If the model configuration has not been loaded.
@@ -104,7 +106,11 @@ class ModelLoadBalancer:
104
106
  for model_config in self.models_config:
105
107
  if model_config.get('deployment_name') == deployment_name:
106
108
  model_id = model_config['id']
107
- return self.models[model_id]
109
+ model = self.models[model_id]
110
+ if with_metadata:
111
+ return model, deployment_name
112
+ return model
113
+
108
114
  self.logger.error(f"No model found for deployment name: {deployment_name}")
109
115
  raise ValueError(f"No model found for deployment name: {deployment_name}")
110
116
 
@@ -114,9 +120,21 @@ class ModelLoadBalancer:
114
120
  self.logger.error(f"No models found for provider '{provider}' and type '{model_type}'")
115
121
  raise ValueError(f"No models found for provider '{provider}' and type '{model_type}'")
116
122
 
117
- selected_model_config = self._round_robin_selection(candidates)
123
+ if selection_strategy == 'random':
124
+ selected_model_config = self._random_selection(candidates)
125
+ elif selection_strategy == 'round_robin':
126
+ selected_model_config = self._round_robin_selection(candidates)
127
+ elif selection_strategy == 'least_used':
128
+ selected_model_config = self._least_used_selection(candidates)
129
+ else:
130
+ self.logger.warning(f"Unsupported selection strategy: '{selection_strategy}'. Defaulting to 'random'.")
131
+ selected_model_config = self._random_selection(candidates)
132
+
118
133
  model_id = selected_model_config['id']
119
- return self.models[model_id]
134
+ model = self.models[model_id]
135
+ if with_metadata:
136
+ return model, selected_model_config.get('deployment_name')
137
+ return model
120
138
 
121
139
  raise ValueError("Either 'deployment_name' or both 'provider' and 'model_type' must be provided.")
122
140
 
@@ -179,6 +197,12 @@ class ModelLoadBalancer:
179
197
  self.usage_counter = defaultdict(int)
180
198
  self.current_indices = {}
181
199
 
200
+ def _random_selection(self, candidates: list) -> Dict:
201
+ """Selects a model randomly from a list of candidates."""
202
+ model = random.choice(candidates)
203
+ self.usage_counter[model['id']] += 1
204
+ return model
205
+
182
206
  def _round_robin_selection(self, candidates: list) -> Dict:
183
207
  if id(candidates) not in self.current_indices:
184
208
  self.current_indices[id(candidates)] = 0
@@ -190,8 +214,8 @@ class ModelLoadBalancer:
190
214
  return model
191
215
 
192
216
  def _least_used_selection(self, candidates: list) -> Dict:
193
- min_usage = min(self.usage_counter[m['model_id']] for m in candidates)
194
- least_used = [m for m in candidates if self.usage_counter[m['model_id']] == min_usage]
217
+ min_usage = min(self.usage_counter[m['id']] for m in candidates)
218
+ least_used = [m for m in candidates if self.usage_counter[m['id']] == min_usage]
195
219
  model = random.choice(least_used)
196
220
  self.usage_counter[model['id']] += 1
197
221
  return model
@@ -10,6 +10,7 @@ from langchain_milvus import Milvus
10
10
  from langchain_core.embeddings import Embeddings
11
11
  from langchain_openai import AzureOpenAIEmbeddings
12
12
  from pymilvus import MilvusClient
13
+ import time
13
14
 
14
15
  from ...services.init_services import get_model_balancer
15
16
  from .schema_milvus import SchemaMilvus, DEFAULT_SCHEMA
@@ -361,10 +362,9 @@ class VDBService(object):
361
362
  "params": {}
362
363
  }
363
364
 
364
- vdb = Milvus(
365
- embedding_function=embeddings,
365
+ vdb = self._create_milvus_instance_with_retry(
366
366
  collection_name=collection_name,
367
- connection_args=self.connection_args,
367
+ embeddings=embeddings,
368
368
  index_params=index_params
369
369
  )
370
370
 
@@ -373,6 +373,32 @@ class VDBService(object):
373
373
 
374
374
  return vdb
375
375
 
376
+ def _create_milvus_instance_with_retry(self, collection_name: str, embeddings: Embeddings, index_params: dict) -> Milvus:
377
+ """
378
+ Creates a Milvus instance with a retry mechanism for connection failures.
379
+ """
380
+ retries = 2
381
+ for attempt in range(retries + 1):
382
+ try:
383
+ vdb = Milvus(
384
+ embedding_function=embeddings,
385
+ collection_name=collection_name,
386
+ connection_args=self.connection_args,
387
+ index_params=index_params
388
+ )
389
+ self.logger.info(f"Successfully connected to Milvus for collection '{collection_name}' on attempt {attempt + 1}.")
390
+ return vdb # Return on success
391
+ except Exception as e:
392
+ self.logger.warning(
393
+ f"Attempt {attempt + 1}/{retries + 1} to connect to Milvus for collection '{collection_name}' failed: {e}"
394
+ )
395
+ if attempt < retries:
396
+ self.logger.info("Retrying in 3 seconds...")
397
+ time.sleep(3)
398
+ else:
399
+ self.logger.error(f"Failed to connect to Milvus for collection '{collection_name}' after {retries + 1} attempts.")
400
+ raise RuntimeError(f"Could not connect to Milvus after {retries + 1} attempts.") from e
401
+
376
402
  def drop_collection(self, collection_name: str) -> None:
377
403
  """
378
404
  Deletes a collection from the vector database and removes it from the cache.
@@ -6,7 +6,7 @@ build-backend = "pdm.backend"
6
6
 
7
7
  [project]
8
8
  name = "crewplus"
9
- version = "0.2.28"
9
+ version = "0.2.30"
10
10
  description = "Base services for CrewPlus AI applications"
11
11
  authors = [
12
12
  { name = "Tim Liu", email = "tim@opsmateai.com" },
File without changes
File without changes
File without changes
File without changes