ouroboros-ai 0.2.0__py3-none-any.whl → 0.2.2__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.

Potentially problematic release.


This version of ouroboros-ai might be problematic. Click here for more details.

@@ -36,8 +36,8 @@ DEFAULT_MODEL = "openrouter/google/gemini-2.0-flash-001"
36
36
  # Temperature for reproducible scoring
37
37
  SCORING_TEMPERATURE = 0.1
38
38
 
39
- # Maximum token limit to prevent cost explosion
40
- MAX_TOKEN_LIMIT = 8192
39
+ # Maximum token limit (None = no limit, rely on model's context window)
40
+ MAX_TOKEN_LIMIT: int | None = None
41
41
 
42
42
 
43
43
  class ComponentScore(BaseModel):
@@ -110,15 +110,15 @@ class AmbiguityScorer:
110
110
  from interview conversation, producing reproducible scores.
111
111
 
112
112
  Uses adaptive token allocation: starts with `initial_max_tokens` and
113
- doubles on truncation up to `MAX_TOKEN_LIMIT`. Retries up to `max_retries`
114
- times on both provider errors and parse failures.
113
+ doubles on truncation up to `MAX_TOKEN_LIMIT`. Retries until success
114
+ by default (unlimited), or up to `max_retries` if specified.
115
115
 
116
116
  Attributes:
117
117
  llm_adapter: The LLM adapter for completions.
118
118
  model: Model identifier to use.
119
119
  temperature: Temperature for reproducibility (default 0.1).
120
120
  initial_max_tokens: Starting token limit (default 2048).
121
- max_retries: Maximum retry attempts (default 3).
121
+ max_retries: Maximum retry attempts, or None for unlimited (default).
122
122
 
123
123
  Example:
124
124
  scorer = AmbiguityScorer(llm_adapter=LiteLLMAdapter())
@@ -138,7 +138,7 @@ class AmbiguityScorer:
138
138
  model: str = DEFAULT_MODEL
139
139
  temperature: float = SCORING_TEMPERATURE
140
140
  initial_max_tokens: int = 2048
141
- max_retries: int = 3
141
+ max_retries: int | None = None # None = unlimited retries
142
142
 
143
143
  async def score(
144
144
  self, state: InterviewState
@@ -180,8 +180,15 @@ class AmbiguityScorer:
180
180
  current_max_tokens = self.initial_max_tokens
181
181
  last_error: Exception | ProviderError | None = None
182
182
  last_response: str = ""
183
+ attempt = 0
184
+
185
+ while True:
186
+ # Check retry limit if set
187
+ if self.max_retries is not None and attempt >= self.max_retries:
188
+ break
189
+
190
+ attempt += 1
183
191
 
184
- for attempt in range(self.max_retries):
185
192
  config = CompletionConfig(
186
193
  model=self.model,
187
194
  temperature=self.temperature,
@@ -190,15 +197,15 @@ class AmbiguityScorer:
190
197
 
191
198
  result = await self.llm_adapter.complete(messages, config)
192
199
 
193
- # Fix #3: Retry on provider errors (rate limits, transient failures)
200
+ # Retry on provider errors (rate limits, transient failures)
194
201
  if result.is_err:
195
202
  last_error = result.error
196
203
  log.warning(
197
204
  "ambiguity.scoring.provider_error_retrying",
198
205
  interview_id=state.interview_id,
199
206
  error=str(result.error),
200
- attempt=attempt + 1,
201
- max_retries=self.max_retries,
207
+ attempt=attempt,
208
+ max_retries=self.max_retries or "unlimited",
202
209
  )
203
210
  continue
204
211
 
@@ -221,7 +228,7 @@ class AmbiguityScorer:
221
228
  constraint_clarity=breakdown.constraint_clarity.clarity_score,
222
229
  success_criteria_clarity=breakdown.success_criteria_clarity.clarity_score,
223
230
  tokens_used=current_max_tokens,
224
- attempt=attempt + 1,
231
+ attempt=attempt,
225
232
  )
226
233
 
227
234
  return Result.ok(ambiguity_score)
@@ -230,17 +237,19 @@ class AmbiguityScorer:
230
237
  last_error = e
231
238
  last_response = result.value.content
232
239
 
233
- # Fix #2: Only increase tokens if response was truncated
240
+ # Only increase tokens if response was truncated
234
241
  is_truncated = result.value.finish_reason == "length"
235
242
 
236
243
  if is_truncated:
237
- # Fix #1: Cap token growth with MAX_TOKEN_LIMIT
238
- next_tokens = min(current_max_tokens * 2, MAX_TOKEN_LIMIT)
244
+ # Double tokens on truncation, capped at MAX_TOKEN_LIMIT if set
245
+ next_tokens = current_max_tokens * 2
246
+ if MAX_TOKEN_LIMIT is not None:
247
+ next_tokens = min(next_tokens, MAX_TOKEN_LIMIT)
239
248
  log.warning(
240
249
  "ambiguity.scoring.truncated_retrying",
241
250
  interview_id=state.interview_id,
242
251
  error=str(e),
243
- attempt=attempt + 1,
252
+ attempt=attempt,
244
253
  current_tokens=current_max_tokens,
245
254
  next_tokens=next_tokens,
246
255
  )
@@ -251,11 +260,11 @@ class AmbiguityScorer:
251
260
  "ambiguity.scoring.format_error_retrying",
252
261
  interview_id=state.interview_id,
253
262
  error=str(e),
254
- attempt=attempt + 1,
263
+ attempt=attempt,
255
264
  finish_reason=result.value.finish_reason,
256
265
  )
257
266
 
258
- # All retries exhausted
267
+ # All retries exhausted (only reached if max_retries is set)
259
268
  log.warning(
260
269
  "ambiguity.scoring.failed",
261
270
  interview_id=state.interview_id,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ouroboros-ai
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Self-Improving AI Workflow System
5
5
  Author-email: Q00 <jqyu.lee@gmail.com>
6
6
  License-File: LICENSE
@@ -2,7 +2,7 @@ ouroboros/__init__.py,sha256=lmQgHmNOWxGlmwayNvp1ckCuJycL8WzX5Y-7IzrFaVM,701
2
2
  ouroboros/__main__.py,sha256=f_qnL0zPJwh9kfQqynX5adpqzj8ilj94zW5Q2loqGxE,168
3
3
  ouroboros/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  ouroboros/bigbang/__init__.py,sha256=9xGqOYwMKBifb7QVwonc_wndNLMZb7ZH7xgMHaz_70A,951
5
- ouroboros/bigbang/ambiguity.py,sha256=hm-6LeuD_j14uzgZ2wnbBYq4Q24J7kEk4ag0DO0JtAU,18516
5
+ ouroboros/bigbang/ambiguity.py,sha256=pmvahQP41OVL8o6N7DkNHM8zqsLYYhem_CfM2X5xuGE,18911
6
6
  ouroboros/bigbang/interview.py,sha256=zm1VrDNqE8ouGG62h8qnNkIpnUf3HHv4NjzMKDIaWcY,17147
7
7
  ouroboros/bigbang/seed_generator.py,sha256=7MY9a7Eua_zVGDWIVDlzOZJjeAwz0DRatXJg0PvMgiY,20082
8
8
  ouroboros/cli/__init__.py,sha256=CRpxsqJadZL7bCS-yrULWC51tqPKfPsxQLgt0JiwP4g,225
@@ -75,8 +75,8 @@ ouroboros/routing/tiers.py,sha256=QhBQUOo2-h5Z3dEtC0lcOzkRnqTi2W7Jl46750AVNig,73
75
75
  ouroboros/secondary/__init__.py,sha256=kYQ7C4bnBzwDlPrU8qZrOPr2ZuTBaftGktOXl5WZl5Q,1123
76
76
  ouroboros/secondary/scheduler.py,sha256=sPVVWJ1q0yewRAM-Rm1j_HMerSe4cavIvP9z4xlUuL4,13737
77
77
  ouroboros/secondary/todo_registry.py,sha256=4W3C9Uro29VrVLCPKUlpH_BYpzQSbRNW1oMnDYyEhEw,13880
78
- ouroboros_ai-0.2.0.dist-info/METADATA,sha256=-znRAEKqEghugiU67FXrH52Hyt4kBtigrQvwXW-3J_E,19661
79
- ouroboros_ai-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
80
- ouroboros_ai-0.2.0.dist-info/entry_points.txt,sha256=MoETHup6rVkR6AsyjoRzAgIuvVtYYm3Jw40itV3_VyI,53
81
- ouroboros_ai-0.2.0.dist-info/licenses/LICENSE,sha256=n2X-q26TqpXnoBo0t_WouhFxWw663_q5FmbYDZayoHo,1060
82
- ouroboros_ai-0.2.0.dist-info/RECORD,,
78
+ ouroboros_ai-0.2.2.dist-info/METADATA,sha256=v_WwLBVh1qLB3vaFS2PwNCiODepMmq-zitj82ty4jPs,19661
79
+ ouroboros_ai-0.2.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
80
+ ouroboros_ai-0.2.2.dist-info/entry_points.txt,sha256=MoETHup6rVkR6AsyjoRzAgIuvVtYYm3Jw40itV3_VyI,53
81
+ ouroboros_ai-0.2.2.dist-info/licenses/LICENSE,sha256=n2X-q26TqpXnoBo0t_WouhFxWw663_q5FmbYDZayoHo,1060
82
+ ouroboros_ai-0.2.2.dist-info/RECORD,,