code-puppy 0.0.144__py3-none-any.whl → 0.0.145__py3-none-any.whl
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.
- code_puppy/model_factory.py +4 -1
- code_puppy/round_robin_model.py +25 -6
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.145.dist-info}/METADATA +5 -2
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.145.dist-info}/RECORD +8 -8
- {code_puppy-0.0.144.data → code_puppy-0.0.145.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.145.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.145.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.145.dist-info}/licenses/LICENSE +0 -0
code_puppy/model_factory.py
CHANGED
|
@@ -255,6 +255,9 @@ class ModelFactory:
|
|
|
255
255
|
if not model_names or not isinstance(model_names, list):
|
|
256
256
|
raise ValueError(f"Round-robin model '{model_name}' requires a 'models' list in its configuration.")
|
|
257
257
|
|
|
258
|
+
# Get the rotate_every parameter (default: 1)
|
|
259
|
+
rotate_every = model_config.get("rotate_every", 1)
|
|
260
|
+
|
|
258
261
|
# Resolve each model name to an actual model instance
|
|
259
262
|
models = []
|
|
260
263
|
for name in model_names:
|
|
@@ -263,7 +266,7 @@ class ModelFactory:
|
|
|
263
266
|
models.append(model)
|
|
264
267
|
|
|
265
268
|
# Create and return the round-robin model
|
|
266
|
-
return RoundRobinModel(*models)
|
|
269
|
+
return RoundRobinModel(*models, rotate_every=rotate_every)
|
|
267
270
|
|
|
268
271
|
else:
|
|
269
272
|
raise ValueError(f"Unsupported model type: {model_type}")
|
code_puppy/round_robin_model.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
from contextlib import asynccontextmanager, suppress
|
|
2
3
|
from dataclasses import dataclass, field
|
|
3
4
|
from typing import Any, Callable, AsyncIterator, List
|
|
@@ -29,26 +30,39 @@ class RoundRobinModel(Model):
|
|
|
29
30
|
models: List[Model]
|
|
30
31
|
_current_index: int = field(default=0, repr=False)
|
|
31
32
|
_model_name: str = field(repr=False)
|
|
33
|
+
_rotate_every: int = field(default=1, repr=False)
|
|
34
|
+
_request_count: int = field(default=0, repr=False)
|
|
32
35
|
|
|
33
36
|
def __init__(
|
|
34
37
|
self,
|
|
35
|
-
*models: Model
|
|
38
|
+
*models: Model,
|
|
39
|
+
rotate_every: int = 1,
|
|
40
|
+
settings: ModelSettings | None = None
|
|
36
41
|
):
|
|
37
42
|
"""Initialize a round-robin model instance.
|
|
38
43
|
|
|
39
44
|
Args:
|
|
40
|
-
models: The
|
|
45
|
+
models: The model instances to cycle through.
|
|
46
|
+
rotate_every: Number of requests before rotating to the next model (default: 1).
|
|
47
|
+
settings: Model settings that will be used as defaults for this model.
|
|
41
48
|
"""
|
|
42
|
-
super().__init__()
|
|
49
|
+
super().__init__(settings=settings)
|
|
43
50
|
if not models:
|
|
44
51
|
raise ValueError("At least one model must be provided")
|
|
45
|
-
|
|
52
|
+
if rotate_every < 1:
|
|
53
|
+
raise ValueError("rotate_every must be at least 1")
|
|
54
|
+
self.models = list(models)
|
|
46
55
|
self._current_index = 0
|
|
56
|
+
self._request_count = 0
|
|
57
|
+
self._rotate_every = rotate_every
|
|
47
58
|
|
|
48
59
|
@property
|
|
49
60
|
def model_name(self) -> str:
|
|
50
61
|
"""The model name showing this is a round-robin model with its candidates."""
|
|
51
|
-
|
|
62
|
+
base_name = f'round_robin:{",".join(model.model_name for model in self.models)}'
|
|
63
|
+
if self._rotate_every != 1:
|
|
64
|
+
return f'{base_name}:rotate_every={self._rotate_every}'
|
|
65
|
+
return base_name
|
|
52
66
|
|
|
53
67
|
@property
|
|
54
68
|
def system(self) -> str:
|
|
@@ -63,7 +77,10 @@ class RoundRobinModel(Model):
|
|
|
63
77
|
def _get_next_model(self) -> Model:
|
|
64
78
|
"""Get the next model in the round-robin sequence and update the index."""
|
|
65
79
|
model = self.models[self._current_index]
|
|
66
|
-
self.
|
|
80
|
+
self._request_count += 1
|
|
81
|
+
if self._request_count >= self._rotate_every:
|
|
82
|
+
self._current_index = (self._current_index + 1) % len(self.models)
|
|
83
|
+
self._request_count = 0
|
|
67
84
|
return model
|
|
68
85
|
|
|
69
86
|
async def request(
|
|
@@ -74,6 +91,7 @@ class RoundRobinModel(Model):
|
|
|
74
91
|
) -> ModelResponse:
|
|
75
92
|
"""Make a request using the next model in the round-robin sequence."""
|
|
76
93
|
current_model = self._get_next_model()
|
|
94
|
+
# Use the current model's settings as base, then merge with provided settings
|
|
77
95
|
merged_settings = merge_model_settings(current_model.settings, model_settings)
|
|
78
96
|
customized_model_request_parameters = current_model.customize_request_parameters(model_request_parameters)
|
|
79
97
|
|
|
@@ -96,6 +114,7 @@ class RoundRobinModel(Model):
|
|
|
96
114
|
) -> AsyncIterator[StreamedResponse]:
|
|
97
115
|
"""Make a streaming request using the next model in the round-robin sequence."""
|
|
98
116
|
current_model = self._get_next_model()
|
|
117
|
+
# Use the current model's settings as base, then merge with provided settings
|
|
99
118
|
merged_settings = merge_model_settings(current_model.settings, model_settings)
|
|
100
119
|
customized_model_request_parameters = current_model.customize_request_parameters(model_request_parameters)
|
|
101
120
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.145
|
|
4
4
|
Summary: Code generation agent
|
|
5
5
|
Project-URL: repository, https://github.com/mpfaffenberger/code_puppy
|
|
6
6
|
Project-URL: HomePage, https://github.com/mpfaffenberger/code_puppy
|
|
@@ -234,13 +234,16 @@ export CEREBRAS_API_KEY3=csk-...
|
|
|
234
234
|
},
|
|
235
235
|
"cerebras_round_robin": {
|
|
236
236
|
"type": "round_robin",
|
|
237
|
-
"models": ["qwen1", "qwen2", "qwen3"]
|
|
237
|
+
"models": ["qwen1", "qwen2", "qwen3"],
|
|
238
|
+
"rotate_every": 5
|
|
238
239
|
}
|
|
239
240
|
}
|
|
240
241
|
```
|
|
241
242
|
|
|
242
243
|
Then just use /model and tab to select your round-robin model!
|
|
243
244
|
|
|
245
|
+
The `rotate_every` parameter controls how many requests are made to each model before rotating to the next one. In this example, the round-robin model will use each Qwen model for 5 consecutive requests before moving to the next model in the sequence.
|
|
246
|
+
|
|
244
247
|
### Benefits
|
|
245
248
|
- **Rate Limit Protection**: Automatically distribute requests across multiple models
|
|
246
249
|
- **Load Balancing**: Share workload between different model providers
|
|
@@ -6,10 +6,10 @@ code_puppy/config.py,sha256=9yWKHKjLJ2Ddl4frrBI9VRIwPvoWpIx1fAd1YpAvOSQ,15330
|
|
|
6
6
|
code_puppy/http_utils.py,sha256=BAvt4hed7fVMXglA7eS9gOb08h2YTuOyai6VmQq09fg,3432
|
|
7
7
|
code_puppy/main.py,sha256=Vv5HSJnkgZhCvvOoXrJ2zqM5P-i47-RcYAU00Z1Pfx0,21733
|
|
8
8
|
code_puppy/message_history_processor.py,sha256=O2rKp7W6YeIg93W8b0XySTUEQgIZm0f_06--_kzHugM,16145
|
|
9
|
-
code_puppy/model_factory.py,sha256
|
|
9
|
+
code_puppy/model_factory.py,sha256=-_0kJ7qYmRTDk0v3mfp-UrYf0IaDLyG8IMBweDECwJg,11917
|
|
10
10
|
code_puppy/models.json,sha256=dAfpMMI2EEeOMv0ynHSmMuJAYDLcZrs5gCLX3voC4-A,3252
|
|
11
11
|
code_puppy/reopenable_async_client.py,sha256=4UJRaMp5np8cbef9F0zKQ7TPKOfyf5U-Kv-0zYUWDho,8274
|
|
12
|
-
code_puppy/round_robin_model.py,sha256=
|
|
12
|
+
code_puppy/round_robin_model.py,sha256=VWGCbK0-0rLpnrdxlmND5JsKXiNZZWFMIjF4_OL3STE,5594
|
|
13
13
|
code_puppy/state_management.py,sha256=o4mNBCPblRyVrNBH-992-1YqffgH6AKHU7iZRqgP1LI,5925
|
|
14
14
|
code_puppy/status_display.py,sha256=F6eEAkGePDp4StM2BWj-uLLQTDGtJrf0IufzCeP1rRg,8336
|
|
15
15
|
code_puppy/summarization_agent.py,sha256=-e6yUGZ22ahSaF0y7QhgVcQBfx5ktNUkPxBIWQfPaA4,3275
|
|
@@ -126,9 +126,9 @@ code_puppy/tui/tests/test_sidebar_history_navigation.py,sha256=JGiyua8A2B8dLfwiE
|
|
|
126
126
|
code_puppy/tui/tests/test_status_bar.py,sha256=nYT_FZGdmqnnbn6o0ZuOkLtNUtJzLSmtX8P72liQ5Vo,1797
|
|
127
127
|
code_puppy/tui/tests/test_timestamped_history.py,sha256=nVXt9hExZZ_8MFP-AZj4L4bB_1Eo_mc-ZhVICzTuw3I,1799
|
|
128
128
|
code_puppy/tui/tests/test_tools.py,sha256=kgzzAkK4r0DPzQwHHD4cePpVNgrHor6cFr05Pg6DBWg,2687
|
|
129
|
-
code_puppy-0.0.
|
|
130
|
-
code_puppy-0.0.
|
|
131
|
-
code_puppy-0.0.
|
|
132
|
-
code_puppy-0.0.
|
|
133
|
-
code_puppy-0.0.
|
|
134
|
-
code_puppy-0.0.
|
|
129
|
+
code_puppy-0.0.145.data/data/code_puppy/models.json,sha256=dAfpMMI2EEeOMv0ynHSmMuJAYDLcZrs5gCLX3voC4-A,3252
|
|
130
|
+
code_puppy-0.0.145.dist-info/METADATA,sha256=i8WX2P4dcHB7_rGZGug23IafcwjtNPYsy1rcSbsKm9o,22019
|
|
131
|
+
code_puppy-0.0.145.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
132
|
+
code_puppy-0.0.145.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
|
|
133
|
+
code_puppy-0.0.145.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
|
134
|
+
code_puppy-0.0.145.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|