Conversation
|
Warning Rate limit exceeded@KaQuMiQ has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 31 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (7)
WalkthroughThe changes increment the project version and update several dependencies and development tools in the project configuration. The public API surface of the ✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 4
🔭 Outside diff range comments (1)
src/draive/evaluation/score.py (1)
105-107: Inconsistent hashing forEvaluationScore
__eq__says two scores are equal if their numericvalueis equal.
__hash__now defaults to identity, breaking the invarianta == b ⇒ hash(a) == hash(b).Proposed implementation:
- def __hash__(self) -> int: # explicitly using super to silence warnings - return super().__hash__() + def __hash__(self) -> int: + # Hash must mirror equality semantics + return hash(self.value)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (7)
pyproject.toml(3 hunks)src/draive/__init__.py(9 hunks)src/draive/evaluation/evaluator.py(1 hunks)src/draive/evaluation/score.py(1 hunks)src/draive/mcp/server.py(1 hunks)src/draive/parameters/model.py(1 hunks)src/draive/stages/stage.py(2 hunks)
🔇 Additional comments (4)
src/draive/stages/stage.py (2)
1143-1149: Potential loss of disposable-providedStateobjectsPreviously:
async with ctx_disposables as features: with ctx.updated(*features):guaranteed that every
Stateyielded by the disposables was injected into the context.
The refactor keeps theasync withbut drops the secondctx.updated(*features)layer:async with ctx_disposables: return await execution(state=state)If the new
haiway.Disposablescontract no longer yieldsStateobjects or now pushes them to
ctxinternally, this is fine.
If it still yields, the producedStates are now silently ignored, which will break any
down-stream code that relied on them.Please verify the new contract and, if necessary, re-introduce
ctx.updated(*features)or a
similar mechanism.
1161-1173: Same omission when bothstateanddisposablesare suppliedThe mixed branch also removed
*featuresfrom the context update:async with ctx_disposables: with ctx.updated(ctx_state, *states, ctx.state(Processing)):Any
Stateproduced byctx_disposablesmay be lost.Double-check that this is intentional; otherwise the same fix as above applies.
src/draive/__init__.py (1)
12-15: New haiway re-exports lack defensive import error handlingThe freshly added symbols (
File,FileAccess,LoggerObservability,ScopeContext,
StateContext,getenv_base64,process_concurrently,without_missing) are
hard-imported. If users install an earlierhaiwaythan required,ImportError
will surface at import-time, even for code paths that do not use these names.You did bump the minimal version to
haiway~=0.22(pyproject.toml), so that should
protect us, but projects often vendor‐lock older versions.
At minimum, ensure CI/publishing enforces the new requirement; optionally wrap the
imports in a version check to emit a clearer message.Also applies to: 22-22, 25-25, 36-36, 45-45, 52-52
pyproject.toml (1)
24-25: Sanity-check freshly pinned versions before mergingLarge jumps (
openai 1.64 → 1.88,anthropic 0.47 → 0.54, …) occasionally introduce
backwards-incompatible API tweaks.Consider running the quick scan below to spot obvious breaking changes or yanked releases:
#!/usr/bin/env bash # Rough check that all pinned versions exist on PyPI for pkg in numpy==2.2 haiway==0.22 cohere==5.15 openai==1.88 anthropic==0.54 \ mistralai==1.8 google-genai==1.20 ollama==0.5 boto3==1.38 mcp==1.9; do python - <<PY import json, sys, urllib.request, urllib.error, re name, ver = "$pkg".split("==") try: data = json.load(urllib.request.urlopen(f"https://pypi.org/pypi/{name}/{ver}/json")) except urllib.error.HTTPError: print(f"❌ {pkg} not found on PyPI", file=sys.stderr) PY doneAlso applies to: 33-42, 55-56, 63-64
| def __hash__(self) -> int: | ||
| hash_values: list[int] = [] | ||
| for key in self.__PARAMETERS__.keys(): | ||
| value: Any = getattr(self, key, MISSING) | ||
|
|
||
| # Skip MISSING values to ensure consistent hashing | ||
| if value is MISSING: | ||
| continue | ||
|
|
||
| # Convert to hashable representation | ||
| try: | ||
| hash_values.append(hash(value)) | ||
|
|
||
| except TypeError: | ||
| continue # skip unhashable | ||
|
|
||
| return hash((self.__class__, tuple(hash_values))) |
There was a problem hiding this comment.
🛠️ Refactor suggestion
__hash__ breaks for the base DataModel and can silently collide
-
self.__PARAMETERS__may be the sentinelMISSING(e.g. on the un-parameterised base class).
Calling.keys()on it raisesAttributeError, sohash(DataModel())will blow up. -
Skipping every unhashable value means two non-equal models can share the same hash, increasing
the collision rate for sets / dict keys that use these instances.
Proposed minimal fix – guard for the sentinel and include a fallback hashing strategy:
def __hash__(self) -> int:
- hash_values: list[int] = []
- for key in self.__PARAMETERS__.keys():
+ # Base class or invalid state – nothing to hash, but keep instances usable
+ if self.__PARAMETERS__ is MISSING:
+ return hash((self.__class__, ()))
+
+ hash_values: list[int] = []
+ for key in self.__PARAMETERS__:
value: Any = getattr(self, key, MISSING)
@@
- return hash((self.__class__, tuple(hash_values)))
+ return hash((self.__class__, tuple(hash_values)))(Optional) To further reduce collisions, consider recursively converting common container
types (list, set, dict) into hashable equivalents instead of silently skipping them.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def __hash__(self) -> int: | |
| hash_values: list[int] = [] | |
| for key in self.__PARAMETERS__.keys(): | |
| value: Any = getattr(self, key, MISSING) | |
| # Skip MISSING values to ensure consistent hashing | |
| if value is MISSING: | |
| continue | |
| # Convert to hashable representation | |
| try: | |
| hash_values.append(hash(value)) | |
| except TypeError: | |
| continue # skip unhashable | |
| return hash((self.__class__, tuple(hash_values))) | |
| def __hash__(self) -> int: | |
| # Base class or invalid state – nothing to hash, but keep instances usable | |
| if self.__PARAMETERS__ is MISSING: | |
| return hash((self.__class__, ())) | |
| hash_values: list[int] = [] | |
| for key in self.__PARAMETERS__: | |
| value: Any = getattr(self, key, MISSING) | |
| # Skip MISSING values to ensure consistent hashing | |
| if value is MISSING: | |
| continue | |
| # Convert to hashable representation | |
| try: | |
| hash_values.append(hash(value)) | |
| except TypeError: | |
| continue # skip unhashable | |
| return hash((self.__class__, tuple(hash_values))) |
🤖 Prompt for AI Agents
In src/draive/parameters/model.py around lines 616 to 632, the __hash__ method
fails when self.__PARAMETERS__ is the sentinel MISSING, causing an
AttributeError on .keys(). To fix this, first check if self.__PARAMETERS__ is
MISSING and handle that case separately to avoid the error. Additionally,
instead of skipping unhashable values which can cause hash collisions, implement
a fallback hashing strategy that converts common container types like list, set,
and dict into hashable equivalents (e.g., tuples or frozensets) before hashing.
This will reduce silent collisions and improve hash uniqueness.
No description provided.