Skip to content

Comments

Refine toolbox and extend tool handling modes#374

Merged
KaQuMiQ merged 1 commit intomainfrom
feature/tool_handling
Jul 23, 2025
Merged

Refine toolbox and extend tool handling modes#374
KaQuMiQ merged 1 commit intomainfrom
feature/tool_handling

Conversation

@KaQuMiQ
Copy link
Collaborator

@KaQuMiQ KaQuMiQ commented Jul 23, 2025

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Jul 23, 2025

Caution

Review failed

The pull request is closed.

"""

Walkthrough

This change introduces extensive updates across the codebase to enhance tool invocation, error handling, and result aggregation in the Draive framework. The tool handling system is refactored to support multiple handling modes ("auto", "extend", "direct", "spawn"), with corresponding updates to type annotations, protocols, and implementation logic. The ToolError class replaces ToolException, and all related error formatting and availability checking mechanisms are updated for consistency and to use the new tools_turn parameter. The toolbox logic is revised to use tool_turns_limit instead of repeated_calls_limit, and tool usage is now tracked by turns rather than repetition level. The completion and generation flows for text, models, and conversations are refactored to accumulate result extensions and support new tool response types, with streaming text generation removed. The LMM tool request and response types are extended to cover new handling categories, and multiple instantiations now use factory methods. Public API signatures and type annotations are updated throughout to reflect these changes. Additionally, enhanced debug logging is added in key areas to trace tool requests, responses, and completions.

Estimated code review effort

5 (~150–180 minutes)

Possibly related PRs

  • Add tool call stage #344: The main PR significantly extends and refines the Stage.tool_call method introduced in this PR by adding multiple tool handling modes, enhanced error handling, and richer tool response processing, indicating a direct and strong connection at the code level between the two PRs.
  • Add stage router #322: Both PRs modify src/draive/stages/stage.py and related modules, introducing a new StageState class and routing mechanism, sharing direct and significant changes to the same classes and functions in the stage system.
  • Add debug logs to realtime conversation #335: Both PRs modify src/draive/conversation/realtime/default.py by adding debug logging and improving observability, with this PR adding warnings for unsupported tool response types and refining event handling without altering core control flow, indicating a related focus on realtime conversation enhancements.
    """

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd2d567 and c76c72d.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • pyproject.toml (1 hunks)
  • src/draive/__init__.py (2 hunks)
  • src/draive/anthropic/lmm_generation.py (1 hunks)
  • src/draive/choice/default.py (2 hunks)
  • src/draive/conversation/completion/default.py (3 hunks)
  • src/draive/conversation/realtime/default.py (5 hunks)
  • src/draive/generation/model/default.py (2 hunks)
  • src/draive/generation/model/state.py (1 hunks)
  • src/draive/generation/model/types.py (2 hunks)
  • src/draive/generation/text/default.py (3 hunks)
  • src/draive/generation/text/state.py (1 hunks)
  • src/draive/generation/text/types.py (0 hunks)
  • src/draive/lmm/__init__.py (0 hunks)
  • src/draive/lmm/types.py (3 hunks)
  • src/draive/mcp/client.py (4 hunks)
  • src/draive/mistral/lmm_generation.py (2 hunks)
  • src/draive/ollama/lmm_generation.py (2 hunks)
  • src/draive/openai/lmm_generation.py (2 hunks)
  • src/draive/stages/stage.py (2 hunks)
  • src/draive/tools/__init__.py (2 hunks)
  • src/draive/tools/function.py (16 hunks)
  • src/draive/tools/toolbox.py (11 hunks)
  • src/draive/tools/types.py (4 hunks)
  • src/draive/vllm/lmm_generation.py (2 hunks)
  • tests/test_tool_call.py (2 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🔭 Outside diff range comments (3)
src/draive/generation/model/default.py (1)

27-36: Missing generic type parameter for decoder

The decoder parameter should use the generic type to ensure type safety consistency with the protocol definition.

-    decoder: ModelGeneratorDecoder | None,
+    decoder: ModelGeneratorDecoder[Generated] | None,
src/draive/conversation/completion/default.py (1)

167-330: Complex but well-structured streaming implementation.

The refactored streaming logic correctly handles concurrent tool execution and incremental result streaming. The use of asyncio.wait with FIRST_COMPLETED is an excellent choice for processing tool responses as they complete.

Consider adding more inline documentation to explain the complex async flow, particularly around the concurrent tool handling logic (lines 262-292).

src/draive/tools/toolbox.py (1)

176-176: Missing required parameter in available() calls

According to the Tool protocol, the available() method requires a tools_turn parameter, but it's being called without any arguments here.

Apply this fix:

-        elif self.suggest_call.available:  # use suggested tool if able
+        elif self.suggest_call.available(tools_turn):  # use suggested tool if able
-            tuple(tool.specification for tool in self.tools.values() if tool.available),
+            tuple(tool.specification for tool in self.tools.values() if tool.available(tools_turn)),

Also applies to: 187-187

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef9c89e and e591a64.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (22)
  • pyproject.toml (1 hunks)
  • src/draive/__init__.py (2 hunks)
  • src/draive/anthropic/lmm_generation.py (1 hunks)
  • src/draive/choice/default.py (2 hunks)
  • src/draive/conversation/completion/default.py (3 hunks)
  • src/draive/generation/model/default.py (2 hunks)
  • src/draive/generation/model/state.py (1 hunks)
  • src/draive/generation/model/types.py (2 hunks)
  • src/draive/generation/text/default.py (3 hunks)
  • src/draive/generation/text/state.py (1 hunks)
  • src/draive/generation/text/types.py (0 hunks)
  • src/draive/lmm/types.py (3 hunks)
  • src/draive/mcp/client.py (1 hunks)
  • src/draive/mistral/lmm_generation.py (2 hunks)
  • src/draive/ollama/lmm_generation.py (2 hunks)
  • src/draive/openai/lmm_generation.py (2 hunks)
  • src/draive/stages/stage.py (2 hunks)
  • src/draive/tools/__init__.py (2 hunks)
  • src/draive/tools/function.py (16 hunks)
  • src/draive/tools/toolbox.py (10 hunks)
  • src/draive/tools/types.py (4 hunks)
  • src/draive/vllm/lmm_generation.py (2 hunks)
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.py: Use absolute imports from draive package
Follow Ruff import ordering (standard library, third party, local)
Use Python 3.12+ type features (type unions with |, generic syntax)
Use base and abstract types like Sequence or Iterable instead of concrete types
Use custom exceptions for specific errors
Use NumPy docstring convention for all functions, classes, and methods
Skip module-level docstrings unless explicitly requested
Include sections: Parameters, Returns, Raises, Notes (if needed) in docstrings
ALWAYS use Sequence[T] instead of list[T], Mapping[K,V] instead of dict[K,V], and Set[T] instead of set[T] for collections in State, Config and DataModel classes
Immutable updates to State, Config, and DataModel classes should be performed through the .updated() method

Files:

  • src/draive/mcp/client.py
  • src/draive/tools/__init__.py
  • src/draive/generation/model/state.py
  • src/draive/vllm/lmm_generation.py
  • src/draive/__init__.py
  • src/draive/ollama/lmm_generation.py
  • src/draive/openai/lmm_generation.py
  • src/draive/anthropic/lmm_generation.py
  • src/draive/generation/model/types.py
  • src/draive/generation/text/state.py
  • src/draive/choice/default.py
  • src/draive/conversation/completion/default.py
  • src/draive/generation/model/default.py
  • src/draive/lmm/types.py
  • src/draive/generation/text/default.py
  • src/draive/tools/function.py
  • src/draive/mistral/lmm_generation.py
  • src/draive/stages/stage.py
  • src/draive/tools/types.py
  • src/draive/tools/toolbox.py
**/__init__.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

Put exported symbols into __init__.py

Files:

  • src/draive/tools/__init__.py
  • src/draive/__init__.py
🧠 Learnings (7)
pyproject.toml (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: draive builds on top of haiway and exports its symbols

src/draive/tools/__init__.py (3)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use absolute imports from draive package

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/init.py : Put exported symbols into __init__.py

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use custom exceptions for specific errors

src/draive/__init__.py (4)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use absolute imports from draive package

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/init.py : Put exported symbols into __init__.py

Learnt from: KaQuMiQ
PR: #338
File: src/draive/lmm/init.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: draive builds on top of haiway and exports its symbols

src/draive/generation/text/state.py (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use base and abstract types like Sequence or Iterable instead of concrete types

src/draive/conversation/completion/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/generation/text/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/tools/types.py (1)

Learnt from: KaQuMiQ
PR: #327
File: src/draive/helpers/instruction_preparation.py:28-34
Timestamp: 2025-05-28T17:41:57.460Z
Learning: The draive project uses and requires Python 3.12+, so PEP-695 generic syntax with square brackets (e.g., def func[T: Type]()) is valid and should be used instead of the older TypeVar approach.

🧬 Code Graph Analysis (8)
src/draive/tools/__init__.py (1)
src/draive/tools/types.py (1)
  • ToolError (24-31)
src/draive/generation/model/state.py (1)
src/draive/generation/model/types.py (1)
  • ModelGeneratorDecoder (17-21)
src/draive/__init__.py (1)
src/draive/tools/types.py (1)
  • ToolError (24-31)
src/draive/ollama/lmm_generation.py (1)
src/draive/lmm/types.py (10)
  • LMMToolRequests (289-306)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
src/draive/openai/lmm_generation.py (2)
src/draive/lmm/types.py (10)
  • LMMToolRequests (289-306)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
src/draive/ollama/lmm_generation.py (3)
  • lmm_completion (41-51)
  • lmm_completion (54-64)
  • lmm_completion (66-175)
src/draive/anthropic/lmm_generation.py (2)
src/draive/lmm/types.py (11)
  • LMMToolRequests (289-306)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
  • LMMToolRequest (265-286)
src/draive/tools/function.py (5)
  • call (186-253)
  • tool (289-308)
  • tool (312-361)
  • tool (365-410)
  • tool (413-443)
src/draive/tools/function.py (4)
src/draive/utils/processing.py (4)
  • Processing (103-209)
  • event (164-168)
  • event (172-180)
  • event (183-205)
src/draive/tools/types.py (7)
  • ToolAvailabilityChecking (35-40)
  • ToolResultFormatting (44-48)
  • ToolErrorFormatting (52-56)
  • handling (77-77)
  • meta (74-74)
  • call (84-89)
  • name (62-62)
src/draive/multimodal/content.py (2)
  • meta (151-164)
  • MultimodalContent (24-236)
src/draive/lmm/types.py (10)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
  • LMMToolError (132-139)
src/draive/tools/toolbox.py (3)
src/draive/tools/types.py (4)
  • meta (74-74)
  • Tool (60-89)
  • call (84-89)
  • handling (77-77)
src/draive/multimodal/content.py (2)
  • meta (151-164)
  • MultimodalContent (24-236)
src/draive/lmm/types.py (11)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
  • LMMToolResponse (193-217)
  • LMMToolError (132-139)
💤 Files with no reviewable changes (1)
  • src/draive/generation/text/types.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.py: Use absolute imports from draive package
Follow Ruff import ordering (standard library, third party, local)
Use Python 3.12+ type features (type unions with |, generic syntax)
Use base and abstract types like Sequence or Iterable instead of concrete types
Use custom exceptions for specific errors
Use NumPy docstring convention for all functions, classes, and methods
Skip module-level docstrings unless explicitly requested
Include sections: Parameters, Returns, Raises, Notes (if needed) in docstrings
ALWAYS use Sequence[T] instead of list[T], Mapping[K,V] instead of dict[K,V], and Set[T] instead of set[T] for collections in State, Config and DataModel classes
Immutable updates to State, Config, and DataModel classes should be performed through the .updated() method

Files:

  • src/draive/mcp/client.py
  • src/draive/tools/__init__.py
  • src/draive/generation/model/state.py
  • src/draive/vllm/lmm_generation.py
  • src/draive/__init__.py
  • src/draive/ollama/lmm_generation.py
  • src/draive/openai/lmm_generation.py
  • src/draive/anthropic/lmm_generation.py
  • src/draive/generation/model/types.py
  • src/draive/generation/text/state.py
  • src/draive/choice/default.py
  • src/draive/conversation/completion/default.py
  • src/draive/generation/model/default.py
  • src/draive/lmm/types.py
  • src/draive/generation/text/default.py
  • src/draive/tools/function.py
  • src/draive/mistral/lmm_generation.py
  • src/draive/stages/stage.py
  • src/draive/tools/types.py
  • src/draive/tools/toolbox.py
**/__init__.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

Put exported symbols into __init__.py

Files:

  • src/draive/tools/__init__.py
  • src/draive/__init__.py
🧠 Learnings (7)
pyproject.toml (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: draive builds on top of haiway and exports its symbols

src/draive/tools/__init__.py (3)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use absolute imports from draive package

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/init.py : Put exported symbols into __init__.py

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use custom exceptions for specific errors

src/draive/__init__.py (4)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use absolute imports from draive package

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/init.py : Put exported symbols into __init__.py

Learnt from: KaQuMiQ
PR: #338
File: src/draive/lmm/init.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: draive builds on top of haiway and exports its symbols

src/draive/generation/text/state.py (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use base and abstract types like Sequence or Iterable instead of concrete types

src/draive/conversation/completion/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/generation/text/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/tools/types.py (1)

Learnt from: KaQuMiQ
PR: #327
File: src/draive/helpers/instruction_preparation.py:28-34
Timestamp: 2025-05-28T17:41:57.460Z
Learning: The draive project uses and requires Python 3.12+, so PEP-695 generic syntax with square brackets (e.g., def func[T: Type]()) is valid and should be used instead of the older TypeVar approach.

🧬 Code Graph Analysis (8)
src/draive/tools/__init__.py (1)
src/draive/tools/types.py (1)
  • ToolError (24-31)
src/draive/generation/model/state.py (1)
src/draive/generation/model/types.py (1)
  • ModelGeneratorDecoder (17-21)
src/draive/__init__.py (1)
src/draive/tools/types.py (1)
  • ToolError (24-31)
src/draive/ollama/lmm_generation.py (1)
src/draive/lmm/types.py (10)
  • LMMToolRequests (289-306)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
src/draive/openai/lmm_generation.py (2)
src/draive/lmm/types.py (10)
  • LMMToolRequests (289-306)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
src/draive/ollama/lmm_generation.py (3)
  • lmm_completion (41-51)
  • lmm_completion (54-64)
  • lmm_completion (66-175)
src/draive/anthropic/lmm_generation.py (2)
src/draive/lmm/types.py (11)
  • LMMToolRequests (289-306)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
  • LMMToolRequest (265-286)
src/draive/tools/function.py (5)
  • call (186-253)
  • tool (289-308)
  • tool (312-361)
  • tool (365-410)
  • tool (413-443)
src/draive/tools/function.py (4)
src/draive/utils/processing.py (4)
  • Processing (103-209)
  • event (164-168)
  • event (172-180)
  • event (183-205)
src/draive/tools/types.py (7)
  • ToolAvailabilityChecking (35-40)
  • ToolResultFormatting (44-48)
  • ToolErrorFormatting (52-56)
  • handling (77-77)
  • meta (74-74)
  • call (84-89)
  • name (62-62)
src/draive/multimodal/content.py (2)
  • meta (151-164)
  • MultimodalContent (24-236)
src/draive/lmm/types.py (10)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
  • LMMToolError (132-139)
src/draive/tools/toolbox.py (3)
src/draive/tools/types.py (4)
  • meta (74-74)
  • Tool (60-89)
  • call (84-89)
  • handling (77-77)
src/draive/multimodal/content.py (2)
  • meta (151-164)
  • MultimodalContent (24-236)
src/draive/lmm/types.py (11)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (267-281)
  • of (291-302)
  • of (316-327)
  • of (382-392)
  • LMMToolResponse (193-217)
  • LMMToolError (132-139)
🔇 Additional comments (34)
pyproject.toml (1)

24-24: LGTM - Standard dependency update.

The haiway version bump from 0.27.1 to 0.27.2 aligns with the broader tool handling refactoring across the codebase.

src/draive/__init__.py (2)

213-213: LGTM - Consistent exception rename.

The import correctly updates from ToolException to ToolError, aligning with the broader tool error handling refactor.


376-376: LGTM - Export list updated consistently.

The __all__ export correctly reflects the ToolExceptionToolError rename.

src/draive/tools/__init__.py (2)

7-7: LGTM - Import updated consistently.

The import correctly updates from ToolException to ToolError, maintaining consistency with the tool error handling refactor.


18-18: LGTM - Export list synchronized.

The __all__ export correctly reflects the exception rename.

src/draive/mcp/client.py (2)

603-603: LGTM - Parameter name updated consistently.

The parameter rename from availability_check to availability aligns with the broader FunctionTool API refactor.


605-605: LGTM - Error formatting parameter renamed consistently.

The parameter rename from format_failure to format_error maintains consistency with the updated tool error handling terminology.

src/draive/vllm/lmm_generation.py (1)

289-301: LGTM - Factory method pattern adoption.

The change from direct constructor to LMMToolRequests.of() factory method improves API consistency across LMM generation modules while maintaining the same functionality.

src/draive/ollama/lmm_generation.py (1)

147-159: LGTM! Consistent factory method usage.

The refactoring correctly uses LMMToolRequests.of() with the list of LMMToolRequest objects as the first positional argument and content as a keyword argument, aligning with the factory method signature.

src/draive/anthropic/lmm_generation.py (1)

264-275: LGTM! Proper factory method implementation.

The refactoring correctly uses LMMToolRequests.of() with appropriate positional and keyword arguments. The explicit null check in the content expression and the meta=META_EMPTY parameter are properly handled.

src/draive/openai/lmm_generation.py (1)

292-304: LGTM! Consistent factory method refactoring.

The change properly uses LMMToolRequests.of() with the correct argument structure, maintaining consistency with other LMM provider implementations.

src/draive/mistral/lmm_generation.py (1)

269-281: LGTM! Factory method correctly implemented.

The refactoring follows the established pattern of using LMMToolRequests.of() with requests as the first positional argument and content as a keyword argument, maintaining consistency across LMM providers.

src/draive/generation/model/state.py (1)

29-29: LGTM! Improved type safety with generic parameter.

The type annotation correctly adds the Generated type parameter to ModelGeneratorDecoder, ensuring type consistency with the protocol definition and improving type safety throughout the generation pipeline.

src/draive/generation/model/types.py (2)

17-21: Type safety improvement with generic decoder

The introduction of generic typing for ModelGeneratorDecoder improves type safety by ensuring the decoder returns the expected DataModel type rather than a generic dictionary.


36-36: Consistent generic typing for decoder parameter

The decoder parameter correctly uses the generic type, ensuring type consistency between the expected output type and the decoder's return type.

src/draive/generation/text/state.py (2)

2-2: Clean import removal

Correctly removed unused imports after eliminating streaming overloads.


18-35: API simplification by removing streaming parameter

The removal of the stream parameter and associated overloads simplifies the API while maintaining the ability to return either strings or async iterables. This aligns with the broader refactoring to handle streaming at a different layer.

src/draive/generation/model/default.py (2)

90-116: Well-structured tool response handling

The refactored tool handling logic properly distinguishes between different response types (completion, extension, regular) and accumulates results appropriately. The tools_turn counter provides clear tracking of interaction rounds.


118-137: Robust decoding with clear fallback chain

The decoding logic provides a clear hierarchy of decoding attempts with appropriate debug logging and error context. The error handling preserves the exception type and provides useful debugging information.

src/draive/choice/default.py (1)

85-123: Consistent tool handling and proper choice extraction

The implementation follows the established pattern for tool handling with proper accumulation of results. The choice extraction logic correctly parses the accumulated content for the selection.

src/draive/lmm/types.py (2)

190-190: Enhanced tool response handling types

The expansion of handling types supports the new tool interaction patterns with clearer semantics for different response behaviors.


300-305: Good API improvement with non-optional content

Making the content attribute non-optional with a default empty value eliminates the need for None checks and simplifies the API usage.

src/draive/conversation/completion/default.py (1)

111-165: LGTM! The turn-based tool handling is well-implemented.

The refactoring from repetition_level to tools_turn and the addition of extension accumulation logic are correctly implemented. The function properly handles direct completions, extensions, and regular tool responses.

src/draive/tools/types.py (1)

21-90: Well-designed type system improvements.

The changes enhance the tool system's flexibility and consistency:

  • Expanded ToolHandling modes ("auto", "extend", "direct", "spawn") provide richer interaction patterns
  • Renaming to ToolError improves naming consistency
  • Unified use of MultimodalContent throughout
  • Addition of tools_turn parameter enables sophisticated availability control
src/draive/generation/text/default.py (1)

23-102: Clean refactoring with streaming removal.

The simplified non-streaming implementation is cleaner and follows the same turn-based tool handling pattern as other modules. The accumulation of extensions and proper handling of direct completions is correctly implemented.

src/draive/stages/stage.py (2)

756-884: Excellent implementation of multiple tool handling modes.

The enhanced tool_call method properly supports all four handling modes with clear semantics:

  • "auto": Standard tool execution
  • "direct": Tool result replaces stage result
  • "extend": Tool result extends existing result
  • "spawn": Asynchronous execution without waiting

Note that the "spawn" mode (lines 852-861) creates a detached task that may outlive the stage execution. Ensure this is the intended behavior and document any cleanup requirements.


1956-2021: Consistent implementation of turn-based tool handling.

The _lmm_completion function follows the same pattern as other modules with proper handling of completions, extensions, and regular responses. Debug logging provides good observability.

src/draive/tools/function.py (4)

35-167: Consistent naming improvements throughout the class.

The renaming from "failure" to "error" and "availability_check" to "availability" improves API consistency. All changes are properly propagated through constructors, methods, and type annotations.


168-184: Correct implementation of turn-based availability checking.

The available() method now properly accepts and forwards the tools_turn parameter to the availability checking function, enabling sophisticated turn-based tool availability logic.


186-254: Well-structured tool call implementation with proper error handling.

The renamed call() method includes excellent additions:

  • Event reporting for observability (lines 193-200)
  • Proper distinction between Exception (formatted and wrapped) and BaseException (re-raised)
  • Comprehensive telemetry recording

The separation of BaseException handling (lines 240-253) is particularly good as it ensures system exceptions like KeyboardInterrupt aren't caught and formatted as tool errors.


267-271: Helper functions correctly updated.

The _available() function signature and _default_error_format() naming are properly updated to match the new API design.

Also applies to: 466-468

src/draive/tools/toolbox.py (3)

34-34: LGTM! The parameter renaming improves clarity.

The change from repeated_calls_limit to tool_turns_limit better represents the concept of tool usage across multiple conversation turns rather than just repeated calls.

Also applies to: 39-39, 46-46, 66-68, 93-93, 116-116, 122-122


199-202: LGTM! Method call updated correctly.

The change from tool.tool_call to tool.call aligns with the updated Tool protocol.


227-248: LGTM! Tool handling modes properly implemented.

The new handling logic correctly implements the extended tool response modes:

  • "spawn" appropriately uses ctx.spawn() for detached execution
  • Error handling is simplified and catches the specific LMMToolError
  • The f-string usage is more idiomatic

Also applies to: 260-266, 270-270

@KaQuMiQ KaQuMiQ force-pushed the feature/tool_handling branch 4 times, most recently from 6e8fd56 to cd2d567 Compare July 23, 2025 12:25
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🔭 Outside diff range comments (3)
pyproject.toml (1)

48-52: Optional: pin the extra’ed dependency to the same base version for clarity.

The opentelemetry extra currently pulls "haiway[opentelemetry]" without a version spec, which resolves fine thanks to the base requirement (haiway~=0.27.2). Pinning it explicitly avoids accidental drifts if the base line is ever removed.

-  "haiway[opentelemetry]",
+  "haiway[opentelemetry]~=0.27.2",
src/draive/generation/model/default.py (1)

27-36: Type inconsistency in decoder parameter.

The function signature declares decoder: ModelGeneratorDecoder | None without the generic type parameter, but line 121 uses it as decoder(result) expecting it to return Generated. This should be decoder: ModelGeneratorDecoder[Generated] | None to match the protocol definition.

-    decoder: ModelGeneratorDecoder | None,
+    decoder: ModelGeneratorDecoder[Generated] | None,

Also applies to: 120-122

src/draive/generation/text/default.py (1)

23-30: Remove remaining AsyncIterable return types in text generation modules

The streaming types weren’t fully cleaned up—AsyncIterable is still imported and used in several text‐generation files. Please update these signatures to return str only and remove the unused import:

• src/draive/generation/text/state.py
– At top: change
from collections.abc import AsyncIterable, Iterable
to
from collections.abc import Iterable
– Around line 26, update
) -> AsyncIterable[str] | str:
to
) -> str:

• src/draive/generation/text/types.py
– Remove AsyncIterable from the import on line 1.
– At line 22, change
) -> AsyncIterable[str] | str:
to
) -> str:

• src/draive/generation/text/default.py
– Remove AsyncIterable from the import on line 1.
– At line 30, change
) -> AsyncIterable[str] | str:
to
) -> str:

Fix these to fully eliminate the deprecated streaming API.

♻️ Duplicate comments (3)
src/draive/generation/model/default.py (1)

82-84: Good fix for the uninitialized variable issue.

The result variable is now properly initialized with MultimodalContent.empty, addressing the previous review comment about potential access of uninitialized variable.

src/draive/choice/default.py (1)

77-79: Properly initialized variables.

Good that result is initialized with MultimodalContent.empty, addressing the previous review comment about uninitialized variable access.

src/draive/lmm/types.py (1)

236-262: Consider documenting the aggregation logic

The completion() method implements complex aggregation logic. Consider adding a docstring to clarify the precedence and merging behavior.

     def completion(
         self,
         *,
         extension: MultimodalContent | None = None,
     ) -> LMMCompletion | None:
+        """Aggregate completion and extension responses into a single completion.
+        
+        Extensions are prepended to completions in the final content.
+        Metadata is merged from all completion responses.
+        
+        Returns:
+            Aggregated completion or None if no completion responses exist.
+        """
         completion_parts: list[MultimodalContent] = []
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e591a64 and cd2d567.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • pyproject.toml (1 hunks)
  • src/draive/__init__.py (2 hunks)
  • src/draive/anthropic/lmm_generation.py (1 hunks)
  • src/draive/choice/default.py (2 hunks)
  • src/draive/conversation/completion/default.py (3 hunks)
  • src/draive/conversation/realtime/default.py (4 hunks)
  • src/draive/generation/model/default.py (2 hunks)
  • src/draive/generation/model/state.py (1 hunks)
  • src/draive/generation/model/types.py (2 hunks)
  • src/draive/generation/text/default.py (3 hunks)
  • src/draive/generation/text/state.py (1 hunks)
  • src/draive/generation/text/types.py (0 hunks)
  • src/draive/lmm/types.py (3 hunks)
  • src/draive/mcp/client.py (1 hunks)
  • src/draive/mistral/lmm_generation.py (2 hunks)
  • src/draive/ollama/lmm_generation.py (2 hunks)
  • src/draive/openai/lmm_generation.py (2 hunks)
  • src/draive/stages/stage.py (2 hunks)
  • src/draive/tools/__init__.py (2 hunks)
  • src/draive/tools/function.py (15 hunks)
  • src/draive/tools/toolbox.py (10 hunks)
  • src/draive/tools/types.py (4 hunks)
  • src/draive/vllm/lmm_generation.py (2 hunks)
  • tests/test_tool_call.py (2 hunks)
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.py: Use absolute imports from draive package
Follow Ruff import ordering (standard library, third party, local)
Use Python 3.12+ type features (type unions with |, generic syntax)
Use base and abstract types like Sequence or Iterable instead of concrete types
Use custom exceptions for specific errors
Use NumPy docstring convention for all functions, classes, and methods
Skip module-level docstrings unless explicitly requested
Include sections: Parameters, Returns, Raises, Notes (if needed) in docstrings
ALWAYS use Sequence[T] instead of list[T], Mapping[K,V] instead of dict[K,V], and Set[T] instead of set[T] for collections in State, Config and DataModel classes
Immutable updates to State, Config, and DataModel classes should be performed through the .updated() method

Files:

  • src/draive/ollama/lmm_generation.py
  • tests/test_tool_call.py
  • src/draive/mcp/client.py
  • src/draive/__init__.py
  • src/draive/tools/__init__.py
  • src/draive/openai/lmm_generation.py
  • src/draive/anthropic/lmm_generation.py
  • src/draive/generation/model/state.py
  • src/draive/mistral/lmm_generation.py
  • src/draive/conversation/realtime/default.py
  • src/draive/generation/model/types.py
  • src/draive/generation/text/state.py
  • src/draive/conversation/completion/default.py
  • src/draive/generation/model/default.py
  • src/draive/choice/default.py
  • src/draive/vllm/lmm_generation.py
  • src/draive/tools/types.py
  • src/draive/lmm/types.py
  • src/draive/generation/text/default.py
  • src/draive/tools/function.py
  • src/draive/stages/stage.py
  • src/draive/tools/toolbox.py
tests/**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

tests/**/*.py: Tests should use pytest with async support and be located in the tests/ directory
Mock dependencies within scope using stubbed functionality state in tests

Files:

  • tests/test_tool_call.py
**/__init__.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

Put exported symbols into __init__.py

Files:

  • src/draive/__init__.py
  • src/draive/tools/__init__.py
🧠 Learnings (8)
src/draive/__init__.py (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use absolute imports from draive package

src/draive/tools/__init__.py (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use absolute imports from draive package

src/draive/conversation/realtime/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/generation/text/state.py (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use base and abstract types like Sequence or Iterable instead of concrete types

src/draive/conversation/completion/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/tools/types.py (1)

Learnt from: KaQuMiQ
PR: #327
File: src/draive/helpers/instruction_preparation.py:28-34
Timestamp: 2025-05-28T17:41:57.460Z
Learning: The draive project uses and requires Python 3.12+, so PEP-695 generic syntax with square brackets (e.g., def func[T: Type]()) is valid and should be used instead of the older TypeVar approach.

src/draive/lmm/types.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/generation/text/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

🧬 Code Graph Analysis (8)
src/draive/__init__.py (1)
src/draive/tools/types.py (1)
  • ToolError (24-31)
src/draive/tools/__init__.py (1)
src/draive/tools/types.py (1)
  • ToolError (24-31)
src/draive/openai/lmm_generation.py (2)
src/draive/lmm/types.py (10)
  • LMMToolRequests (293-310)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (271-285)
  • of (295-306)
  • of (320-331)
  • of (386-396)
src/draive/ollama/lmm_generation.py (3)
  • lmm_completion (41-51)
  • lmm_completion (54-64)
  • lmm_completion (66-175)
src/draive/generation/model/state.py (1)
src/draive/generation/model/types.py (1)
  • ModelGeneratorDecoder (17-21)
src/draive/conversation/completion/default.py (5)
src/draive/lmm/types.py (16)
  • LMMCompletion (162-179)
  • completion (236-261)
  • LMMToolRequests (293-310)
  • LMMToolResponses (220-266)
  • completion_extension (263-266)
  • LMMToolRequest (269-290)
  • LMMToolResponse (193-217)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (271-285)
  • of (295-306)
  • of (320-331)
  • of (386-396)
src/draive/multimodal/content.py (4)
  • MultimodalContent (24-236)
  • appending (189-219)
  • meta (151-164)
  • of (28-50)
src/draive/tools/toolbox.py (4)
  • available_tools (156-189)
  • respond_all (207-217)
  • respond (219-276)
  • of (28-124)
src/draive/conversation/types.py (5)
  • ConversationMessage (79-227)
  • model (46-64)
  • model (163-177)
  • ConversationMessageChunk (23-76)
  • of (232-249)
src/draive/instructions/types.py (7)
  • Instruction (45-224)
  • formatted (48-53)
  • formatted (57-62)
  • formatted (65-83)
  • of (87-96)
  • of (100-109)
  • of (112-146)
src/draive/generation/model/default.py (5)
src/draive/parameters/model.py (2)
  • DataModel (386-756)
  • from_json (723-738)
src/draive/multimodal/content.py (2)
  • MultimodalContent (24-236)
  • appending (189-219)
src/draive/lmm/state.py (4)
  • LMM (27-84)
  • completion (30-39)
  • completion (43-52)
  • completion (55-82)
src/draive/lmm/types.py (5)
  • completion (236-261)
  • LMMCompletion (162-179)
  • LMMToolRequests (293-310)
  • LMMToolResponses (220-266)
  • completion_extension (263-266)
src/draive/tools/toolbox.py (2)
  • available_tools (156-189)
  • respond_all (207-217)
src/draive/generation/text/default.py (4)
src/draive/multimodal/content.py (3)
  • MultimodalContent (24-236)
  • appending (189-219)
  • to_str (176-187)
src/draive/lmm/state.py (4)
  • LMM (27-84)
  • completion (30-39)
  • completion (43-52)
  • completion (55-82)
src/draive/lmm/types.py (5)
  • completion (236-261)
  • LMMCompletion (162-179)
  • LMMToolRequests (293-310)
  • LMMToolResponses (220-266)
  • completion_extension (263-266)
src/draive/tools/toolbox.py (2)
  • available_tools (156-189)
  • respond_all (207-217)
src/draive/tools/function.py (3)
src/draive/tools/types.py (8)
  • ToolAvailabilityChecking (35-40)
  • ToolResultFormatting (44-48)
  • ToolErrorFormatting (52-56)
  • handling (77-77)
  • meta (74-74)
  • available (79-82)
  • call (84-89)
  • name (62-62)
src/draive/multimodal/content.py (2)
  • meta (151-164)
  • MultimodalContent (24-236)
src/draive/utils/processing.py (3)
  • event (164-168)
  • event (172-180)
  • event (183-205)
💤 Files with no reviewable changes (1)
  • src/draive/generation/text/types.py
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.py: Use absolute imports from draive package
Follow Ruff import ordering (standard library, third party, local)
Use Python 3.12+ type features (type unions with |, generic syntax)
Use base and abstract types like Sequence or Iterable instead of concrete types
Use custom exceptions for specific errors
Use NumPy docstring convention for all functions, classes, and methods
Skip module-level docstrings unless explicitly requested
Include sections: Parameters, Returns, Raises, Notes (if needed) in docstrings
ALWAYS use Sequence[T] instead of list[T], Mapping[K,V] instead of dict[K,V], and Set[T] instead of set[T] for collections in State, Config and DataModel classes
Immutable updates to State, Config, and DataModel classes should be performed through the .updated() method

Files:

  • src/draive/ollama/lmm_generation.py
  • tests/test_tool_call.py
  • src/draive/mcp/client.py
  • src/draive/__init__.py
  • src/draive/tools/__init__.py
  • src/draive/openai/lmm_generation.py
  • src/draive/anthropic/lmm_generation.py
  • src/draive/generation/model/state.py
  • src/draive/mistral/lmm_generation.py
  • src/draive/conversation/realtime/default.py
  • src/draive/generation/model/types.py
  • src/draive/generation/text/state.py
  • src/draive/conversation/completion/default.py
  • src/draive/generation/model/default.py
  • src/draive/choice/default.py
  • src/draive/vllm/lmm_generation.py
  • src/draive/tools/types.py
  • src/draive/lmm/types.py
  • src/draive/generation/text/default.py
  • src/draive/tools/function.py
  • src/draive/stages/stage.py
  • src/draive/tools/toolbox.py
tests/**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

tests/**/*.py: Tests should use pytest with async support and be located in the tests/ directory
Mock dependencies within scope using stubbed functionality state in tests

Files:

  • tests/test_tool_call.py
**/__init__.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

Put exported symbols into __init__.py

Files:

  • src/draive/__init__.py
  • src/draive/tools/__init__.py
🧠 Learnings (8)
src/draive/__init__.py (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use absolute imports from draive package

src/draive/tools/__init__.py (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use absolute imports from draive package

src/draive/conversation/realtime/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/generation/text/state.py (1)

Learnt from: CR
PR: miquido/draive#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T11:09:57.256Z
Learning: Applies to **/*.py : Use base and abstract types like Sequence or Iterable instead of concrete types

src/draive/conversation/completion/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/tools/types.py (1)

Learnt from: KaQuMiQ
PR: #327
File: src/draive/helpers/instruction_preparation.py:28-34
Timestamp: 2025-05-28T17:41:57.460Z
Learning: The draive project uses and requires Python 3.12+, so PEP-695 generic syntax with square brackets (e.g., def func[T: Type]()) is valid and should be used instead of the older TypeVar approach.

src/draive/lmm/types.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

src/draive/generation/text/default.py (1)

Learnt from: KaQuMiQ
PR: #338
File: src/draive/bedrock/lmm_generation.py:102-107
Timestamp: 2025-06-16T09:44:08.688Z
Learning: LMMInstruction is a type alias for str in the draive codebase, so LMMInstruction and str are equivalent types and can be used interchangeably.

🧬 Code Graph Analysis (8)
src/draive/__init__.py (1)
src/draive/tools/types.py (1)
  • ToolError (24-31)
src/draive/tools/__init__.py (1)
src/draive/tools/types.py (1)
  • ToolError (24-31)
src/draive/openai/lmm_generation.py (2)
src/draive/lmm/types.py (10)
  • LMMToolRequests (293-310)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (271-285)
  • of (295-306)
  • of (320-331)
  • of (386-396)
src/draive/ollama/lmm_generation.py (3)
  • lmm_completion (41-51)
  • lmm_completion (54-64)
  • lmm_completion (66-175)
src/draive/generation/model/state.py (1)
src/draive/generation/model/types.py (1)
  • ModelGeneratorDecoder (17-21)
src/draive/conversation/completion/default.py (5)
src/draive/lmm/types.py (16)
  • LMMCompletion (162-179)
  • completion (236-261)
  • LMMToolRequests (293-310)
  • LMMToolResponses (220-266)
  • completion_extension (263-266)
  • LMMToolRequest (269-290)
  • LMMToolResponse (193-217)
  • of (85-108)
  • of (144-153)
  • of (164-173)
  • of (195-211)
  • of (222-231)
  • of (271-285)
  • of (295-306)
  • of (320-331)
  • of (386-396)
src/draive/multimodal/content.py (4)
  • MultimodalContent (24-236)
  • appending (189-219)
  • meta (151-164)
  • of (28-50)
src/draive/tools/toolbox.py (4)
  • available_tools (156-189)
  • respond_all (207-217)
  • respond (219-276)
  • of (28-124)
src/draive/conversation/types.py (5)
  • ConversationMessage (79-227)
  • model (46-64)
  • model (163-177)
  • ConversationMessageChunk (23-76)
  • of (232-249)
src/draive/instructions/types.py (7)
  • Instruction (45-224)
  • formatted (48-53)
  • formatted (57-62)
  • formatted (65-83)
  • of (87-96)
  • of (100-109)
  • of (112-146)
src/draive/generation/model/default.py (5)
src/draive/parameters/model.py (2)
  • DataModel (386-756)
  • from_json (723-738)
src/draive/multimodal/content.py (2)
  • MultimodalContent (24-236)
  • appending (189-219)
src/draive/lmm/state.py (4)
  • LMM (27-84)
  • completion (30-39)
  • completion (43-52)
  • completion (55-82)
src/draive/lmm/types.py (5)
  • completion (236-261)
  • LMMCompletion (162-179)
  • LMMToolRequests (293-310)
  • LMMToolResponses (220-266)
  • completion_extension (263-266)
src/draive/tools/toolbox.py (2)
  • available_tools (156-189)
  • respond_all (207-217)
src/draive/generation/text/default.py (4)
src/draive/multimodal/content.py (3)
  • MultimodalContent (24-236)
  • appending (189-219)
  • to_str (176-187)
src/draive/lmm/state.py (4)
  • LMM (27-84)
  • completion (30-39)
  • completion (43-52)
  • completion (55-82)
src/draive/lmm/types.py (5)
  • completion (236-261)
  • LMMCompletion (162-179)
  • LMMToolRequests (293-310)
  • LMMToolResponses (220-266)
  • completion_extension (263-266)
src/draive/tools/toolbox.py (2)
  • available_tools (156-189)
  • respond_all (207-217)
src/draive/tools/function.py (3)
src/draive/tools/types.py (8)
  • ToolAvailabilityChecking (35-40)
  • ToolResultFormatting (44-48)
  • ToolErrorFormatting (52-56)
  • handling (77-77)
  • meta (74-74)
  • available (79-82)
  • call (84-89)
  • name (62-62)
src/draive/multimodal/content.py (2)
  • meta (151-164)
  • MultimodalContent (24-236)
src/draive/utils/processing.py (3)
  • event (164-168)
  • event (172-180)
  • event (183-205)
🔇 Additional comments (35)
pyproject.toml (1)

24-24: Verified: haiway 0.27.2 is available and supports Python 3.12
The PyPI release metadata includes wheels tagged for cp312/py3, so you can safely merge.

src/draive/__init__.py (1)

213-213: LGTM! Consistent exception class renaming.

The import and export of ToolError correctly replaces ToolException, aligning with the broader codebase refactoring where the exception class was renamed and now requires a MultimodalContent parameter.

Also applies to: 376-376

tests/test_tool_call.py (1)

54-58: LGTM! Test method calls updated correctly.

The test calls have been properly updated from tool_call to call, maintaining consistency with the renamed tool invocation interface while preserving all test logic and assertions.

Also applies to: 75-79

src/draive/mcp/client.py (1)

603-605: LGTM! Parameter names updated to match new FunctionTool interface.

The parameter renaming from availability_check to availability and format_failure to format_error correctly aligns with the updated FunctionTool constructor signature while maintaining the same functionality.

src/draive/tools/__init__.py (1)

7-7: LGTM! Exception class import and export updated consistently.

The replacement of ToolException with ToolError in both import and export statements correctly reflects the exception class renaming and maintains proper module interface consistency.

Also applies to: 18-18

src/draive/ollama/lmm_generation.py (1)

147-159: LGTM! Standardized LMMToolRequests instantiation using factory method.

The refactoring to use LMMToolRequests.of() instead of direct constructor call standardizes the creation pattern across the codebase while maintaining the same functionality. The tool requests list and content parameter are properly passed to the factory method.

src/draive/anthropic/lmm_generation.py (1)

264-275: LGTM! Clean refactoring to factory method pattern.

The change standardizes LMMToolRequests instantiation by using the of() factory method instead of direct constructor calls. This improves consistency across LMM generation modules and makes the conditional check more explicit.

src/draive/vllm/lmm_generation.py (1)

289-301: Consistent factory method adoption.

This change aligns with the broader refactoring effort to standardize LMMToolRequests instantiation across all LMM generation modules using the of() factory method.

src/draive/mistral/lmm_generation.py (1)

269-281: Consistent refactoring to factory method.

This change continues the pattern of standardizing LMMToolRequests instantiation across the codebase using the of() factory method, maintaining consistency with other LMM generation modules.

src/draive/openai/lmm_generation.py (1)

292-304: Completes consistent factory method adoption.

This change rounds out the standardization effort across all LMM generation modules, ensuring consistent LMMToolRequests instantiation using the of() factory method.

src/draive/generation/model/state.py (1)

29-29: Improved type annotation with explicit generic constraint.

The change makes the generic type relationship explicit by constraining the decoder parameter to ModelGeneratorDecoder[Generated], which improves type safety and aligns with the generic protocol definition in src/draive/generation/model/types.py.

src/draive/generation/model/types.py (1)

17-21: Good type safety improvements!

The generic parameterization of ModelGeneratorDecoder ensures type consistency between the decoder output and the expected generated model type. This change will help catch type mismatches at compile time.

Also applies to: 36-36

src/draive/conversation/realtime/default.py (1)

76-81: Good improvements to logging and control flow.

The changes enhance observability:

  • Warning logs clearly indicate unsupported tool handling modes in realtime
  • Debug logs help trace various event types during realtime conversation
  • Explicit continue statement clarifies the asynchronous handling pattern

Also applies to: 102-103, 112-113, 120-121, 126-128, 140-140

src/draive/generation/model/default.py (1)

86-116: Well-structured tool response handling.

The new approach properly accumulates partial results:

  • Direct completions from tools break the loop immediately
  • Extensions are accumulated in result_extension
  • Debug logging provides good visibility into the flow
src/draive/choice/default.py (1)

77-111: Consistent implementation with model generation.

The tool response handling pattern matches the implementation in generate_model, maintaining consistency across the codebase:

  • Accumulates extensions before final resolution
  • Handles direct completions appropriately
  • Good debug logging for traceability
src/draive/lmm/types.py (2)

190-190: LGTM! The extended response handling types enhance tool interaction flexibility.

The addition of "completion", "extension", and "detached" handling modes provides more granular control over tool response processing, aligning well with the PR's objective to refine tool handling.


304-304: Good improvement: Consistent non-null content handling.

Using MultimodalContent.empty as the default instead of None eliminates the need for null checks and improves API consistency.

Also applies to: 309-309

src/draive/tools/types.py (5)

21-21: LGTM! Extended tool handling modes enable richer invocation patterns.

The addition of "extend" and "spawn" modes provides valuable flexibility for tool invocation strategies, supporting both result accumulation and detached execution patterns.


24-32: Good refactor: Consistent error handling with required content.

Renaming to ToolError follows Python conventions better, and requiring MultimodalContent ensures errors are always properly formatted for model consumption.


36-40: LGTM! Turn-based availability checking improves clarity.

Using tools_turn instead of repetition-based tracking provides clearer semantics for tool availability checks.


48-48: Good type unification: Consistent use of MultimodalContent.

Standardizing on MultimodalContent for both result and error formatting improves API consistency.

Also applies to: 56-56


79-89: Excellent protocol improvements for better tool lifecycle management.

The changes enhance the Tool protocol:

  • Dynamic availability checking with tools_turn parameter
  • Cleaner method naming with call instead of tool_call
  • Consistent MultimodalContent return type
src/draive/conversation/completion/default.py (3)

1-3: LGTM! Appropriate imports for incremental streaming.

The new imports support the improved streaming implementation with incremental tool response processing.


111-165: Excellent refactor: Turn-based tracking with proper extension accumulation.

The synchronous completion function has been cleanly refactored to:

  • Use turn-based tool tracking for better clarity
  • Properly accumulate and prepend extensions to the final result
  • Handle both direct completions and tool responses with clear control flow
  • Add helpful debug logging throughout

The implementation correctly uses the new completion() and completion_extension() methods from LMMToolResponses.


259-294: Excellent incremental streaming design for tool responses.

The implementation effectively uses asyncio.wait with FIRST_COMPLETED to:

  • Process tool responses as they complete rather than waiting for all
  • Stream completions and extensions immediately to the output
  • Properly track completion status to end streaming when appropriate

This design significantly improves user experience by reducing latency.

src/draive/generation/text/default.py (1)

57-102: Clean implementation with consistent tool handling pattern.

The synchronous text generation implementation:

  • Uses the same turn-based tracking pattern as conversation completion
  • Properly accumulates extensions before appending to results
  • Includes helpful debug logging
  • Cleanly converts the final MultimodalContent to string

The removal of streaming significantly improves code clarity.

src/draive/tools/function.py (4)

25-25: Consistent terminology update: failure → error.

The renaming from "failure" to "error" improves consistency across the codebase and aligns with Python conventions.

Also applies to: 42-44, 106-106


167-183: Good implementation of turn-based availability checking.

The method correctly:

  • Accepts the required tools_turn parameter
  • Passes it to the availability check function
  • Handles exceptions gracefully by returning False and logging the error

226-229: Error handling looks correct.

The code properly uses LMMToolError (imported from draive.lmm) to wrap tool execution errors with formatted content.


307-309: Thorough and consistent updates to tool decorator.

All decorator overloads and the implementation have been properly updated with:

  • Renamed availability and format_error parameters
  • Updated default formatting functions
  • Consistent parameter documentation

Also applies to: 360-361, 409-411, 424-425

src/draive/stages/stage.py (2)

804-878: Well-structured implementation of the new tool handling modes

The refactored tool_call method correctly implements the four handling modes (auto, direct, extend, spawn) with clear separation of concerns. The error handling is properly unified, and the use of ctx.spawn for detached execution is appropriate.


1966-2020: Excellent refactoring of the completion loop with result extension support

The updated _lmm_completion function properly handles the new tool turn semantics and result extension accumulation. The enhanced debug logging at key points will greatly aid in troubleshooting tool interactions.

src/draive/tools/toolbox.py (3)

34-34: Consistent and semantically clearer parameter naming

The renaming from repeated_calls_limit/repetition_level to tool_turns_limit/tools_turn throughout the file better represents the concept of conversation turns with tool interactions rather than simple repetition counting.

Also applies to: 67-68, 93-94, 116-117, 122-123, 132-132, 147-147, 153-153, 159-167, 287-287, 316-316, 324-324


227-248: Well-implemented extended tool handling modes

The response handling correctly maps the four tool handling modes to their corresponding LMM response types. The spawn implementation properly uses ctx.spawn for fire-and-forget execution and returns an appropriate placeholder response.


260-276: Simplified and consistent error handling

The error handling is now more straightforward with a unified "error" handling type for all error cases. The f-string usage for logging is more Pythonic, and the error messages are clearer with the "ERROR:" prefix.

@KaQuMiQ KaQuMiQ force-pushed the feature/tool_handling branch from cd2d567 to c76c72d Compare July 23, 2025 12:43
@KaQuMiQ
Copy link
Collaborator Author

KaQuMiQ commented Jul 23, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jul 23, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@KaQuMiQ KaQuMiQ merged commit 709959e into main Jul 23, 2025
4 of 5 checks passed
@KaQuMiQ KaQuMiQ deleted the feature/tool_handling branch July 23, 2025 12:49
This was referenced Sep 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant