Conversation
|
Caution Review failedThe pull request is closed. WalkthroughBumps package version and adds Mistral moderation support: new MistralModerationConfig, a draive.mistral.moderation module with MistralContentModeration, and re-exports in draive.mistral. Mistral client now includes GuardrailsModeration in its feature set and wiring. OpenAI moderation APIs renamed and reworked (content_guardrails → moderation_guardrails, content_verification → content_moderation) and client import updated. Guardrails moderation payloads and exceptions change from Sequence[str] to Mapping[str, float] across guardrails types, Bedrock guardrails, and provider implementations to carry per-category scores. Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (9)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
pyproject.toml(1 hunks)src/draive/mistral/__init__.py(1 hunks)src/draive/mistral/config.py(2 hunks)src/draive/mistral/moderation.py(1 hunks)src/draive/openai/client.py(2 hunks)src/draive/openai/moderation.py(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Use absolute imports from the draive package (e.g., from draive import ...), not relative imports
Follow Ruff import ordering: standard library, third-party, then local imports
Use Python 3.12+ typing features (e.g., | unions, PEP 695 generics)
Prefer abstract/base collection types (Sequence, Mapping, Set, Iterable) over concrete list, dict, set in type hints
Define and raise custom exception types for specific error cases
Use NumPy docstring convention for all functions, classes, and methods
Skip module-level docstrings unless explicitly requested
Docstrings should include Parameters, Returns, Raises, and Notes (if needed) sectionsFormat all Python code with Ruff formatter (run via
make format); do not use any other formatter
Files:
src/draive/mistral/config.pysrc/draive/openai/client.pysrc/draive/mistral/__init__.pysrc/draive/mistral/moderation.pysrc/draive/openai/moderation.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly asfrom haiway import State, ctx
Usectx.scope(...)to bind activeStateinstances; avoid global state
Route all logging throughctx.log_*and never use
Enforce strict typing on public APIs; avoid untyped definitions andAnyexcept at verified third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamicgetattrexcept at narrow boundaries
Use abstract immutable protocols (Mapping,Sequence,Iterable) instead of concretedict/list/setin public types
Usefinalwhere applicable; prefer composition over complex inheritance
Use precise unions (|), narrow withmatch/isinstance, and avoidcastunless provably safe and localized
Model immutable configuration/data ashaiway.State; avoid in‑place mutation and preferState.updated(...)/functional builders
Access active state viahaiway.ctxwithin async scopes (ctx.scope(...))
Public state methods that dispatch on the active instance must use@statemethod
Add structured, concise logs around generation calls, tool dispatch, and provider requests/responses (without secrets); add metrics viactx.recordwhere applicable
All I/O is async; keep boundaries async, usectx.spawnfor detached tasks, and avoid custom threading
Translate provider/SDK errors into typed exceptions; never raise bareException; preserve context
Compose multimodal content withMultimodalContent.of(...); useResourceContent/Referencefor blobs; wrap custom data inArtifactContent(use hidden when needed)
Public symbols require NumPy-style docstrings with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings for internal helpers; prefer self-explanatory names; skip module-level docstrings
Never log secrets or full request bodies containing keys/tokens
Read credentials from environment variables; resolve via helpers likegetenv_str
Files:
src/draive/mistral/config.pysrc/draive/openai/client.pysrc/draive/mistral/__init__.pysrc/draive/mistral/moderation.pysrc/draive/openai/moderation.py
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/{config,client,api}.py
📄 CodeRabbit inference engine (AGENTS.md)
Provider adapters must include
config.py,client.py, andapi.pywithin each provider package
Files:
src/draive/mistral/config.pysrc/draive/openai/client.py
🧠 Learnings (1)
📚 Learning: 2025-09-11T15:22:15.967Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-09-11T15:22:15.967Z
Learning: Applies to src/draive/__init__.py : Centralize and update all public exports in `src/draive/__init__.py` when API surface changes
Applied to files:
src/draive/mistral/__init__.py
🧬 Code graph analysis (4)
src/draive/openai/client.py (1)
src/draive/openai/moderation.py (2)
OpenAIContentModeration(15-246)moderation_guardrails(16-20)
src/draive/mistral/__init__.py (1)
src/draive/mistral/config.py (3)
MistralChatConfig(12-18)MistralEmbeddingConfig(21-23)MistralModerationConfig(26-27)
src/draive/mistral/moderation.py (8)
src/draive/guardrails/moderation/state.py (1)
GuardrailsModeration(24-102)src/draive/guardrails/moderation/types.py (1)
GuardrailsModerationException(16-29)src/draive/mistral/api.py (1)
MistralAPI(9-51)src/draive/mistral/config.py (1)
MistralModerationConfig(26-27)src/draive/multimodal/content.py (2)
MultimodalContent(25-592)resources(95-125)src/draive/multimodal/artifact.py (1)
ArtifactContent(11-96)src/draive/multimodal/text.py (1)
TextContent(11-82)src/draive/resources/types.py (2)
ResourceContent(126-212)ResourceReference(74-97)
src/draive/openai/moderation.py (1)
src/draive/guardrails/moderation/state.py (1)
GuardrailsModeration(24-102)
🔇 Additional comments (5)
pyproject.toml (1)
8-8: Version bump looks good.The version increment from 0.85.4 to 0.85.5 appropriately reflects the addition of new Mistral moderation features.
src/draive/mistral/config.py (1)
26-27: LGTM! Configuration follows established patterns.The
MistralModerationConfigclass properly extendsConfigurationand provides a sensible default model name.src/draive/openai/moderation.py (1)
16-20: Good API alignment with dual checking.The rename to
moderation_guardrailsbetter describes the functionality, and applying moderation to both input and output is a security best practice.src/draive/openai/client.py (1)
14-14: Import and method call correctly updated.The changes properly reflect the new moderation module structure and API naming.
Also applies to: 89-89
src/draive/mistral/__init__.py (1)
2-2: Add Mistral moderation exports to the top-level APIsrc/draive/mistral/init.py exports MistralModerationConfig (alongside Mistral, MistralChatConfig, MistralEmbeddingConfig), but src/draive/init.py does not re-export them — add the appropriate imports and all entries in src/draive/init.py if these should be exposed at package top-level.
| moderated_content.append(media_ref.to_str()) | ||
|
|
||
| case ArtifactContent() as artifact: | ||
| moderated_content.append(artifact.artifact.to_str()) |
There was a problem hiding this comment.
Ensure hidden artifacts are handled correctly.
The artifact.artifact.to_str() bypasses the ArtifactContent.to_str() method which respects the hidden flag. Hidden artifacts should return empty strings as per the ArtifactContent implementation.
- moderated_content.append(artifact.artifact.to_str())
+ moderated_content.append(artifact.to_str())📝 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.
| moderated_content.append(artifact.artifact.to_str()) | |
| moderated_content.append(artifact.to_str()) |
🤖 Prompt for AI Agents
In src/draive/mistral/moderation.py around line 62, the code appends
artifact.artifact.to_str() which bypasses the Artifact's public to_str() that
enforces the hidden flag; replace that direct inner conversion with a call to
the Artifact object's to_str() (the method that delegates to
ArtifactContent.to_str() and returns an empty string for hidden artifacts) so
hidden artifacts are handled correctly.
| response: ModerationResponse = await self._client.classifiers.moderate_async( | ||
| model=moderation_config.model, | ||
| inputs=moderated_content, | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
Verify the Mistral client has required async moderation methods.
Let me verify that the Mistral client's classifiers module has the moderate_async method as used here.
🏁 Script executed:
#!/bin/bash
# Verify the Mistral SDK has the moderate_async method
# Check if mistralai package documentation or usage exists
echo "Searching for Mistral moderation API usage patterns:"
rg -A5 -B5 "classifiers.moderate" --type py
# Check for any Mistral client initialization or documentation
echo -e "\nChecking Mistral API client structure:"
rg -A10 "from mistralai import" --type py
# Look for any test files that might show usage
echo -e "\nChecking test files for Mistral moderation usage:"
fd -e py -x grep -l "moderate_async\|ModerationResponse" {} \;Length of output: 4289
🌐 Web query:
Does the mistralai Python SDK support classifiers.moderate_async method for content moderation?
💡 Result:
Short answer: No — the official Mistral Python SDK exposes classifiers.moderate and classifiers.moderate_chat (not a classifiers.moderate_async method). See the SDK classifiers docs and package reference. [1][2]
Sources:
- Mistral client-python classifiers README (shows moderate, moderate_chat). [1]
- mistralai Python package details / API listing (shows classifiers: moderate, moderate_chat). [2]
Replace classifiers.moderate_async with supported Mistral moderation API
src/draive/mistral/moderation.py (lines 71–74) calls self._client.classifiers.moderate_async, but the mistralai Python SDK exposes classifiers.moderate and classifiers.moderate_chat (no moderate_async); update the call to use one of the supported methods and reconcile the sync/async boundary and related imports/typing (ModerationResponse).
🤖 Prompt for AI Agents
In src/draive/mistral/moderation.py around lines 71 to 74, the code currently
awaits self._client.classifiers.moderate_async which does not exist in the
mistralai SDK; replace it with a supported API (classifiers.moderate or
classifiers.moderate_chat) and reconcile the sync/async boundary by calling the
synchronous method inside an executor (e.g., asyncio.to_thread) or removing the
await if you convert the function to synchronous. Also update imports/typing for
ModerationResponse to match the return type of the chosen method and adjust any
downstream code that expects the previous async signature.
src/draive/mistral/moderation.py
Outdated
| if result.categories is None: | ||
| continue # skip empty | ||
|
|
||
| for category, flagged in result.categories.items(): | ||
| if flagged: # add all flagged categories | ||
| violations.add(category) |
There was a problem hiding this comment.
🧹 Nitpick
Consider defensive handling of categories structure.
While you check for None categories, the iteration assumes categories is a dictionary when not None. Consider adding more defensive checks or documenting the expected structure.
for result in response.results:
if result.categories is None:
continue # skip empty
+ if not isinstance(result.categories, dict):
+ ctx.log_warning(f"Unexpected categories type: {type(result.categories)}")
+ continue
for category, flagged in result.categories.items():🤖 Prompt for AI Agents
In src/draive/mistral/moderation.py around lines 78 to 83, the code only checks
for None but then assumes result.categories is a dict and calls .items(); add a
defensive check to ensure result.categories is a mapping/dict before iterating
(e.g., isinstance(result.categories, dict)), and if it's not a dict either
convert/coerce it into the expected shape (or skip and optionally log a warning)
so you never call .items() on an unexpected type; also update the function/type
hint or add a short comment documenting the expected categories structure.
| ) -> None: | ||
| moderation_config: OpenAIModerationConfig = config or ctx.state(OpenAIModerationConfig) | ||
| async with ctx.scope("openai_moderation"): | ||
| async with ctx.scope("moderation"): |
There was a problem hiding this comment.
🧹 Nitpick
Consider maintaining provider-specific scope naming.
While "moderation" is cleaner, using "openai_moderation" would maintain consistency with other provider-specific scopes and make it easier to distinguish between different moderation providers in observability data.
- async with ctx.scope("moderation"):
+ async with ctx.scope("openai_moderation"):📝 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.
| async with ctx.scope("moderation"): | |
| async with ctx.scope("openai_moderation"): |
🤖 Prompt for AI Agents
In src/draive/openai/moderation.py around line 31, the scope is currently named
"moderation"; change it to the provider-specific name "openai_moderation" to
match other provider-specific scopes used across the codebase. Update that async
with ctx.scope(...) call to use "openai_moderation" and scan for any related
observability/telemetry code or tests that reference the old "moderation" scope
so they can be adjusted accordingly.
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/draive/mistral/moderation.py (1)
17-91: Add NumPy-style docstring for public class.The public class MistralContentModeration is missing required documentation per coding guidelines.
Add after line 17:
class MistralContentModeration(MistralAPI): """ Mistral API implementation for content moderation. Provides content moderation capabilities using Mistral's moderation API, supporting multimodal content checking for both input and output guardrails. Parameters ---------- server_url : str | None Optional Mistral API server URL. Defaults to MISTRAL_SERVER_URL env var or "https://api.mistral.ai". api_key : str | None Optional Mistral API key. Defaults to MISTRAL_API_KEY env var. timeout : float | None Optional request timeout in seconds. **extra : Any Additional parameters passed to the base API class. """src/draive/openai/client.py (1)
30-33: Adopt NumPy‑style docstring for the public class.Project guidelines require NumPy docstrings for public symbols. Replace the brief sentence with a structured docstring.
- """ - Access to OpenAI services, can be used to prepare various functionalities like lmm. - """ + """ + Access to OpenAI services. + + Parameters + ---------- + base_url : str | None, optional + Base URL for the OpenAI API (overrides environment/default), by default None. + api_key : str | None, optional + API key, by default None (resolved from environment). + organization : str | None, optional + OpenAI organization identifier, by default None. + azure_api_endpoint : str | None, optional + Azure OpenAI endpoint, by default None. + azure_api_version : str | None, optional + Azure OpenAI API version, by default None. + azure_deployment : str | None, optional + Azure OpenAI deployment name, by default None. + timeout : float | None, optional + Client request timeout in seconds, by default None. + features : Collection[type[State]] | None, optional + Enabled feature states to bind on enter. Defaults to + {GenerativeModel, RealtimeGenerativeModel, TextEmbedding, ImageGeneration, GuardrailsModeration}. + **extra : Any + Provider‑specific options forwarded to the underlying client. + + Notes + ----- + Use this class as an async context manager and bind the returned states with `haiway.ctx.scope(...)`. + """
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
pyproject.toml(1 hunks)src/draive/mistral/__init__.py(1 hunks)src/draive/mistral/config.py(2 hunks)src/draive/mistral/moderation.py(1 hunks)src/draive/openai/client.py(2 hunks)src/draive/openai/moderation.py(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Use absolute imports from the draive package (e.g., from draive import ...), not relative imports
Follow Ruff import ordering: standard library, third-party, then local imports
Use Python 3.12+ typing features (e.g., | unions, PEP 695 generics)
Prefer abstract/base collection types (Sequence, Mapping, Set, Iterable) over concrete list, dict, set in type hints
Define and raise custom exception types for specific error cases
Use NumPy docstring convention for all functions, classes, and methods
Skip module-level docstrings unless explicitly requested
Docstrings should include Parameters, Returns, Raises, and Notes (if needed) sectionsFormat all Python code with Ruff formatter (run via
make format); do not use any other formatter
Files:
src/draive/mistral/moderation.pysrc/draive/mistral/__init__.pysrc/draive/mistral/config.pysrc/draive/openai/moderation.pysrc/draive/openai/client.py
src/draive/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/draive/**/*.py: Import Haiway symbols directly asfrom haiway import State, ctx
Usectx.scope(...)to bind activeStateinstances; avoid global state
Route all logging throughctx.log_*and never use
Enforce strict typing on public APIs; avoid untyped definitions andAnyexcept at verified third‑party boundaries
Prefer explicit attribute access with static types; avoid dynamicgetattrexcept at narrow boundaries
Use abstract immutable protocols (Mapping,Sequence,Iterable) instead of concretedict/list/setin public types
Usefinalwhere applicable; prefer composition over complex inheritance
Use precise unions (|), narrow withmatch/isinstance, and avoidcastunless provably safe and localized
Model immutable configuration/data ashaiway.State; avoid in‑place mutation and preferState.updated(...)/functional builders
Access active state viahaiway.ctxwithin async scopes (ctx.scope(...))
Public state methods that dispatch on the active instance must use@statemethod
Add structured, concise logs around generation calls, tool dispatch, and provider requests/responses (without secrets); add metrics viactx.recordwhere applicable
All I/O is async; keep boundaries async, usectx.spawnfor detached tasks, and avoid custom threading
Translate provider/SDK errors into typed exceptions; never raise bareException; preserve context
Compose multimodal content withMultimodalContent.of(...); useResourceContent/Referencefor blobs; wrap custom data inArtifactContent(use hidden when needed)
Public symbols require NumPy-style docstrings with Parameters/Returns/Raises and rationale when non-obvious
Avoid docstrings for internal helpers; prefer self-explanatory names; skip module-level docstrings
Never log secrets or full request bodies containing keys/tokens
Read credentials from environment variables; resolve via helpers likegetenv_str
Files:
src/draive/mistral/moderation.pysrc/draive/mistral/__init__.pysrc/draive/mistral/config.pysrc/draive/openai/moderation.pysrc/draive/openai/client.py
src/draive/{openai,anthropic,mistral,gemini,vllm,ollama,bedrock,cohere}/{config,client,api}.py
📄 CodeRabbit inference engine (AGENTS.md)
Provider adapters must include
config.py,client.py, andapi.pywithin each provider package
Files:
src/draive/mistral/config.pysrc/draive/openai/client.py
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-09-11T15:22:15.967Z
Learning: Applies to src/draive/__init__.py : Centralize and update all public exports in `src/draive/__init__.py` when API surface changes
📚 Learning: 2025-09-11T15:22:15.967Z
Learnt from: CR
PR: miquido/draive#0
File: AGENTS.md:0-0
Timestamp: 2025-09-11T15:22:15.967Z
Learning: Applies to src/draive/__init__.py : Centralize and update all public exports in `src/draive/__init__.py` when API surface changes
Applied to files:
src/draive/mistral/__init__.py
📚 Learning: 2025-09-08T10:32:32.520Z
Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T10:32:32.520Z
Learning: Applies to draive/**/__init__.py : Put exported public symbols into package __init__.py files
Applied to files:
src/draive/mistral/__init__.py
🧬 Code graph analysis (4)
src/draive/mistral/moderation.py (8)
src/draive/guardrails/moderation/state.py (1)
GuardrailsModeration(24-102)src/draive/guardrails/moderation/types.py (1)
GuardrailsModerationException(16-29)src/draive/mistral/api.py (1)
MistralAPI(9-51)src/draive/mistral/config.py (1)
MistralModerationConfig(26-27)src/draive/multimodal/content.py (2)
MultimodalContent(25-592)resources(95-125)src/draive/multimodal/artifact.py (1)
ArtifactContent(11-96)src/draive/multimodal/text.py (1)
TextContent(11-82)src/draive/resources/types.py (2)
ResourceContent(126-212)ResourceReference(74-97)
src/draive/mistral/__init__.py (1)
src/draive/mistral/config.py (3)
MistralChatConfig(12-18)MistralEmbeddingConfig(21-23)MistralModerationConfig(26-27)
src/draive/openai/moderation.py (1)
src/draive/guardrails/moderation/state.py (1)
GuardrailsModeration(24-102)
src/draive/openai/client.py (1)
src/draive/openai/moderation.py (2)
OpenAIContentModeration(15-246)moderation_guardrails(16-20)
🔇 Additional comments (7)
pyproject.toml (1)
8-8: Version bump looks good.The version increment from 0.85.4 to 0.85.5 is appropriate for this new feature addition.
src/draive/mistral/config.py (1)
26-27: LGTM!The MistralModerationConfig follows the established pattern and uses the appropriate default model.
src/draive/openai/moderation.py (2)
16-20: LGTM! Consistent naming improvement.The rename from
content_guardrailstomoderation_guardrailsimproves clarity and consistency.
22-31: Good consistency with method naming.The rename from
content_verificationtocontent_moderationand the scope change from "openai_moderation" to "moderation" provide better consistency across the moderation system.src/draive/mistral/__init__.py (1)
2-9: Export MistralModerationConfig from top-level packagesrc/draive/mistral/init.py exposes MistralModerationConfig, but src/draive/init.py does not—add
from draive.mistral import MistralModerationConfigand include"MistralModerationConfig"in__all__of src/draive/init.py.Likely an incorrect or invalid review comment.
src/draive/mistral/moderation.py (1)
14-14: Verify MistralContentModeration export in package rootSearch returned no matches for MistralContentModeration in src/draive/init.py or src/draive/mistral/init.py — if the class is intended for public use, import it in src/draive/init.py and add to all (or ensure src/draive/mistral/init.py re-exports it).
src/draive/openai/client.py (1)
88-90: Correct use of the renamed API (moderation_guardrails).This aligns with the new guardrails entrypoint and the
GuardrailsModerationfeature gate.
| def content_guardrails(self) -> GuardrailsModeration: | ||
| return GuardrailsModeration( | ||
| input_checking=self.content_verification, | ||
| output_checking=self.content_verification, | ||
| ) |
There was a problem hiding this comment.
🧹 Nitpick
Consider renaming method for consistency.
The method name content_guardrails() differs from the OpenAI implementation's moderation_guardrails(). Consider aligning the naming for consistency across providers.
- def content_guardrails(self) -> GuardrailsModeration:
+ def moderation_guardrails(self) -> GuardrailsModeration:
return GuardrailsModeration(
input_checking=self.content_verification,
output_checking=self.content_verification,
)📝 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 content_guardrails(self) -> GuardrailsModeration: | |
| return GuardrailsModeration( | |
| input_checking=self.content_verification, | |
| output_checking=self.content_verification, | |
| ) | |
| def moderation_guardrails(self) -> GuardrailsModeration: | |
| return GuardrailsModeration( | |
| input_checking=self.content_verification, | |
| output_checking=self.content_verification, | |
| ) |
🤖 Prompt for AI Agents
In src/draive/mistral/moderation.py around lines 18 to 22, rename the method
content_guardrails() to moderation_guardrails() to match the OpenAI
implementation; update the method definition name and all internal
references/imports/usages across the codebase (including tests) to call
moderation_guardrails(), keep the same return type GuardrailsModeration and
behavior, and optionally add a thin compatibility wrapper named
content_guardrails() that forwards to moderation_guardrails() if you need to
avoid breaking callers during the transition.
src/draive/mistral/moderation.py
Outdated
| async def content_verification( # noqa: C901 | ||
| self, | ||
| content: Multimodal, | ||
| /, | ||
| config: MistralModerationConfig, | ||
| **extra: Any, | ||
| ) -> None: |
There was a problem hiding this comment.
🧹 Nitpick
Rename method to align with OpenAI pattern.
For consistency with the OpenAI implementation, consider renaming content_verification to content_moderation.
- async def content_verification( # noqa: C901
+ async def content_moderation( # noqa: C901
self,
content: Multimodal,
/,
config: MistralModerationConfig,
**extra: Any,
) -> None:And update the guardrails method:
def moderation_guardrails(self) -> GuardrailsModeration:
return GuardrailsModeration(
- input_checking=self.content_verification,
- output_checking=self.content_verification,
+ input_checking=self.content_moderation,
+ output_checking=self.content_moderation,
)📝 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.
| async def content_verification( # noqa: C901 | |
| self, | |
| content: Multimodal, | |
| /, | |
| config: MistralModerationConfig, | |
| **extra: Any, | |
| ) -> None: | |
| async def content_moderation( # noqa: C901 | |
| self, | |
| content: Multimodal, | |
| /, | |
| config: MistralModerationConfig, | |
| **extra: Any, | |
| ) -> None: | |
| def moderation_guardrails(self) -> GuardrailsModeration: | |
| return GuardrailsModeration( | |
| input_checking=self.content_moderation, | |
| output_checking=self.content_moderation, | |
| ) |
🤖 Prompt for AI Agents
In src/draive/mistral/moderation.py around lines 24-30, rename the async method
content_verification to content_moderation to match the OpenAI naming pattern;
update the corresponding guardrails method name used inside this module (and any
internal helper names) to the new content_moderation name, then update all call
sites, imports, tests, and documentation to reference content_moderation instead
of content_verification so nothing breaks at runtime; ensure function signature
and behavior remain identical and run the test suite to confirm no remaining
references.
| moderated_content.append(media_ref.to_str()) | ||
|
|
||
| case ArtifactContent() as artifact: | ||
| moderated_content.append(artifact.artifact.to_str()) |
There was a problem hiding this comment.
🧩 Analysis chain
Potential attribute access error on ArtifactContent.
The code assumes all artifacts have a to_str() method, which may not be guaranteed for all DataModel types.
Consider adding a safety check or using the existing to_str() method from ArtifactContent:
- moderated_content.append(artifact.artifact.to_str())
+ moderated_content.append(artifact.to_str())Let's verify the ArtifactContent implementation:
🏁 Script executed:
#!/bin/bash
# Check ArtifactContent's to_str implementation
ast-grep --pattern 'class ArtifactContent {
$$$
def to_str($$$) {
$$$
}
$$$
}'Length of output: 0
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="src/draive/mistral/moderation.py"
if [ -f "$FILE" ]; then
echo "=== $FILE ==="
sed -n '1,240p' "$FILE" || true
else
echo "$FILE not found"
fi
echo
echo "=== rg searches: ArtifactContent / Artifact / to_str / artifact.artifact / artifact.to_str ==="
rg -n -C3 --hidden --no-ignore '\bclass\s+ArtifactContent\b' || true
rg -n -C3 --hidden --no-ignore '\bclass\s+Artifact\b' || true
rg -n -C3 --hidden --no-ignore '\bdef\s+to_str\b' || true
rg -n -C3 --hidden --no-ignore '\bartifact\.artifact\b' || true
rg -n -C3 --hidden --no-ignore '\bartifact\.to_str\b' || true
rg -n -C3 --hidden --no-ignore '\bArtifactContent\b' || true
rg -n -C3 --hidden --no-ignore '\bto_str\s*\(' || trueLength of output: 102991
Replace direct artifact.artifact.to_str() with ArtifactContent.to_str()
ArtifactContent.to_str() already exists and respects the hidden flag (returns "" when hidden); calling artifact.artifact.to_str() bypasses that and can leak hidden payloads — use artifact.to_str() instead.
Location: src/draive/mistral/moderation.py (around lines 61–62). ArtifactContent.to_str is implemented in src/draive/multimodal/artifact.py (def to_str at ~line 82).
Suggested change:
- moderated_content.append(artifact.artifact.to_str())
+ moderated_content.append(artifact.to_str())📝 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.
| moderated_content.append(artifact.artifact.to_str()) | |
| moderated_content.append(artifact.to_str()) |
🤖 Prompt for AI Agents
In src/draive/mistral/moderation.py around line 62, the code calls
artifact.artifact.to_str(), bypassing ArtifactContent.to_str() which respects
the hidden flag and can return an empty string for hidden content; replace the
direct attribute call with artifact.to_str() so the hidden logic is honored and
hidden payloads are not leaked.
| from draive.openai.embedding import OpenAIEmbedding | ||
| from draive.openai.guardrails import OpenAIContentModeration | ||
| from draive.openai.images import OpenAIImageGeneration | ||
| from draive.openai.moderation import OpenAIContentModeration |
There was a problem hiding this comment.
🛠️ Refactor suggestion
🧩 Analysis chain
Import relocation to moderation module looks correct.
Good switch to draive.openai.moderation.OpenAIContentModeration; resolves the new API location.
Run to surface any stale references to the old guardrails API:
🏁 Script executed:
#!/bin/bash
# Find legacy imports and symbols renamed in this PR
rg -nP -C2 $'\bfrom\s+draive\.openai\.guardrails\b|content_guardrails\s*\(|content_verification\s*\('Length of output: 660
Replace remaining guardrails references in src/draive/mistral/moderation.py
Legacy guardrails APIs (content_guardrails, content_verification) are still present — migrate these to the new moderation API or remove the guardrails usage.
- src/draive/mistral/moderation.py: lines ~16–26 —
def content_guardrails(...)andasync def content_verification(...).
🤖 Prompt for AI Agents
src/draive/mistral/moderation.py around lines 16–26: remove or migrate the
legacy guardrails functions content_guardrails(...) and async
content_verification(...); replace their internals to call the new moderation
API (e.g., use the OpenAIContentModeration client from
src/draive/openai/client.py), update imports, adapt parameters and return types
to match the new moderation client, ensure async/await usage and error handling
follow the new API contract, and delete any leftover references to
content_guardrails/content_verification throughout the module.
e108213 to
aa27090
Compare
aa27090 to
3009a26
Compare
No description provided.