-
Notifications
You must be signed in to change notification settings - Fork 52
Added Math Tools #278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release
Are you sure you want to change the base?
Added Math Tools #278
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughAdds a math tools package (arithmetic, sort/rank, array ops), exposes tool schemas and function mappings, and integrates math tools into the tool initialization sequence so they are loaded (and logged) before internet tools. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Agent
participant ToolInit as tools.__init__
participant MathPkg as tools.math
participant Registry as all_tool_functions
Agent->>ToolInit: initialize_tools()
ToolInit->>MathPkg: import `tools`, `tool_functions`
Note right of MathPkg #D6EAF8: exposes schemas + function map
ToolInit->>Registry: merge `math_tool_functions` into registry
ToolInit-->>Agent: tools ready (system + math + internet)
sequenceDiagram
autonumber
participant Agent
participant Runtime as Tool Runtime
participant MathOp as math_operations
participant Callback as result_callback
Agent->>Runtime: call "arithmetic_calculator" with params
Runtime->>MathOp: await arithmetic_calculator(params)
MathOp->>MathOp: validate inputs, compute result
alt success
MathOp-->>Callback: return result
else error
MathOp-->>Callback: return error message
end
Callback-->>Agent: deliver outcome
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
app/agents/voice/automatic/tools/math/__init__.py (1)
3-3: Consider alphabetically sorting__all__.For consistency with isort-style conventions, the
__all__list could be alphabetically sorted.Apply this diff:
-__all__ = ["tools", "tool_functions"] +__all__ = ["tool_functions", "tools"]
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
app/agents/voice/automatic/tools/__init__.py(2 hunks)app/agents/voice/automatic/tools/math/__init__.py(1 hunks)app/agents/voice/automatic/tools/math/math_operations.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.13.1)
app/agents/voice/automatic/tools/math/__init__.py
3-3: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
app/agents/voice/automatic/tools/math/math_operations.py
21-21: Abstract raise to an inner function
(TRY301)
21-21: Avoid specifying long messages outside the exception class
(TRY003)
24-24: Abstract raise to an inner function
(TRY301)
24-24: Avoid specifying long messages outside the exception class
(TRY003)
30-30: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
30-30: Avoid specifying long messages outside the exception class
(TRY003)
38-38: Abstract raise to an inner function
(TRY301)
38-38: Avoid specifying long messages outside the exception class
(TRY003)
48-48: Abstract raise to an inner function
(TRY301)
48-48: Avoid specifying long messages outside the exception class
(TRY003)
50-50: Abstract raise to an inner function
(TRY301)
50-50: Avoid specifying long messages outside the exception class
(TRY003)
56-58: Abstract raise to an inner function
(TRY301)
56-58: Avoid specifying long messages outside the exception class
(TRY003)
63-65: Abstract raise to an inner function
(TRY301)
63-65: Avoid specifying long messages outside the exception class
(TRY003)
68-70: Abstract raise to an inner function
(TRY301)
68-70: Avoid specifying long messages outside the exception class
(TRY003)
74-76: Abstract raise to an inner function
(TRY301)
74-76: Avoid specifying long messages outside the exception class
(TRY003)
81-81: Abstract raise to an inner function
(TRY301)
81-81: Avoid specifying long messages outside the exception class
(TRY003)
83-83: Abstract raise to an inner function
(TRY301)
83-83: Avoid specifying long messages outside the exception class
(TRY003)
87-87: Abstract raise to an inner function
(TRY301)
87-87: Avoid specifying long messages outside the exception class
(TRY003)
90-90: Abstract raise to an inner function
(TRY301)
90-90: Avoid specifying long messages outside the exception class
(TRY003)
97-97: Do not catch blind exception: Exception
(BLE001)
113-113: Abstract raise to an inner function
(TRY301)
113-113: Avoid specifying long messages outside the exception class
(TRY003)
116-116: Abstract raise to an inner function
(TRY301)
116-116: Avoid specifying long messages outside the exception class
(TRY003)
122-122: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
122-122: Avoid specifying long messages outside the exception class
(TRY003)
132-132: Abstract raise to an inner function
(TRY301)
132-132: Avoid specifying long messages outside the exception class
(TRY003)
163-163: Abstract raise to an inner function
(TRY301)
163-163: Avoid specifying long messages outside the exception class
(TRY003)
175-175: Abstract raise to an inner function
(TRY301)
175-175: Avoid specifying long messages outside the exception class
(TRY003)
182-182: Do not catch blind exception: Exception
(BLE001)
197-197: Abstract raise to an inner function
(TRY301)
197-197: Avoid specifying long messages outside the exception class
(TRY003)
200-200: Abstract raise to an inner function
(TRY301)
200-200: Avoid specifying long messages outside the exception class
(TRY003)
206-206: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
206-206: Avoid specifying long messages outside the exception class
(TRY003)
213-213: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
213-213: Avoid specifying long messages outside the exception class
(TRY003)
219-219: Abstract raise to an inner function
(TRY301)
219-219: Avoid specifying long messages outside the exception class
(TRY003)
221-221: Abstract raise to an inner function
(TRY301)
221-221: Avoid specifying long messages outside the exception class
(TRY003)
225-225: Abstract raise to an inner function
(TRY301)
225-225: Avoid specifying long messages outside the exception class
(TRY003)
227-229: Abstract raise to an inner function
(TRY301)
227-229: Avoid specifying long messages outside the exception class
(TRY003)
240-240: Abstract raise to an inner function
(TRY301)
240-240: Avoid specifying long messages outside the exception class
(TRY003)
248-248: Abstract raise to an inner function
(TRY301)
248-248: Avoid specifying long messages outside the exception class
(TRY003)
250-250: Abstract raise to an inner function
(TRY301)
250-250: Avoid specifying long messages outside the exception class
(TRY003)
254-254: Abstract raise to an inner function
(TRY301)
254-254: Avoid specifying long messages outside the exception class
(TRY003)
256-256: Abstract raise to an inner function
(TRY301)
256-256: Avoid specifying long messages outside the exception class
(TRY003)
260-260: Abstract raise to an inner function
(TRY301)
260-260: Avoid specifying long messages outside the exception class
(TRY003)
262-262: Abstract raise to an inner function
(TRY301)
262-262: Avoid specifying long messages outside the exception class
(TRY003)
266-266: Abstract raise to an inner function
(TRY301)
266-266: Avoid specifying long messages outside the exception class
(TRY003)
268-268: Abstract raise to an inner function
(TRY301)
268-268: Avoid specifying long messages outside the exception class
(TRY003)
270-270: Abstract raise to an inner function
(TRY301)
270-270: Avoid specifying long messages outside the exception class
(TRY003)
273-273: Abstract raise to an inner function
(TRY301)
273-273: Avoid specifying long messages outside the exception class
(TRY003)
285-285: Do not catch blind exception: Exception
(BLE001)
🔇 Additional comments (6)
app/agents/voice/automatic/tools/__init__.py (1)
15-16: LGTM! Clean integration of math tools.The math tools are properly imported and integrated into the tool initialization flow. The placement between system and internet tools is logical, and the pattern follows existing conventions for other tool modules.
Also applies to: 63-66
app/agents/voice/automatic/tools/math/math_operations.py (5)
12-99: LGTM! Comprehensive arithmetic operations with proper validation.The arithmetic calculator implementation is solid:
- All operations are mathematically correct
- Edge cases are properly handled (division by zero, negative sqrt, array length validation)
- Type conversion and error handling are appropriate
- Clear error messages guide proper usage
102-184: LGTM! Robust sorting and statistical operations.The sort and rank implementation handles all operations correctly:
- Proper tie handling in rank calculation (same rank for equal values)
- Graceful handling of multiple modes
- Accurate percentile calculation using linear interpolation
- Comprehensive input validation
187-287: LGTM! Correct vector and array operations.The array operations implementation is mathematically sound:
- Cross product formula is correct for 3D vectors
- Magnitude and normalization properly handle edge cases
- Element-wise operations validate array lengths
- Zero division checks are comprehensive
291-382: LGTM! Function schemas accurately match implementations.The three FunctionSchema definitions are well-structured:
- All enum values correspond to implemented operations
- Required vs optional parameters are correctly specified
- Descriptions provide clear guidance on when to use each tool
- The emphatic language ("ALWAYS use this tool") helps ensure consistent LLM tool usage
385-398: LGTM! Clean export structure.The tools schema and function dictionary properly expose all three math operations with consistent naming, enabling seamless integration with the tool initialization system.
e0f4f48 to
c02ac30
Compare
| result = statistics.mode(numbers) | ||
| except statistics.StatisticsError: | ||
| # No unique mode, return the most frequent values | ||
| from collections import Counter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imports at top-level
| required=["operation", "numbers"], | ||
| ) | ||
|
|
||
| array_operations_function = FunctionSchema( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what current tools does require array_operations_function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used when you want to do some operation on respective elements of two arrays. For example, comparing day-wise sales of two weeks. It will perform subtract_arrays to find differences in sales for each day.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
app/agents/voice/automatic/tools/math/math_operations.py (1)
148-158: Move Counter import to top-level.The
Counterimport at line 153 is inside the function body within a try-except block. This was previously flagged by a reviewer. Move this import to the top of the file alongside other imports for consistency and better performance.Apply this diff:
import math import statistics +from collections import Counter from typing import Any, Dict, List, UnionThen remove the import from line 153:
elif operation == "mode": try: result = statistics.mode(numbers) except statistics.StatisticsError: # No unique mode, return the most frequent values - from collections import Counter - counter = Counter(numbers)
🧹 Nitpick comments (1)
app/agents/voice/automatic/tools/math/math_operations.py (1)
217-272: Consider addingstrict=Trueto zip() calls for safety.While the array length validations are present before each zip operation, explicitly adding
strict=Trueto the zip calls would make the safety guarantees more explicit and protect against future refactoring mistakes.Apply this diff to make the safety guarantees explicit:
if operation == "dot_product": if not array2: raise ValueError("Dot product requires both array1 and array2") if len(array1) != len(array2): raise ValueError("Arrays must have the same length for dot product") - result = sum(a * b for a, b in zip(array1, array2)) + result = sum(a * b for a, b in zip(array1, array2, strict=True)) elif operation == "cross_product": # ... cross product code (3D vectors, no zip needed) elif operation == "add_arrays": if not array2: raise ValueError("Array addition requires both array1 and array2") if len(array1) != len(array2): raise ValueError("Arrays must have the same length for addition") - result = [a + b for a, b in zip(array1, array2)] + result = [a + b for a, b in zip(array1, array2, strict=True)] elif operation == "subtract_arrays": if not array2: raise ValueError("Array subtraction requires both array1 and array2") if len(array1) != len(array2): raise ValueError("Arrays must have the same length for subtraction") - result = [a - b for a, b in zip(array1, array2)] + result = [a - b for a, b in zip(array1, array2, strict=True)] elif operation == "multiply_arrays": if not array2: raise ValueError("Array multiplication requires both array1 and array2") if len(array1) != len(array2): raise ValueError("Arrays must have the same length for multiplication") - result = [a * b for a, b in zip(array1, array2)] + result = [a * b for a, b in zip(array1, array2, strict=True)] elif operation == "divide_arrays": if not array2: raise ValueError("Array division requires both array1 and array2") if len(array1) != len(array2): raise ValueError("Arrays must have the same length for division") if any(b == 0 for b in array2): raise ValueError("Cannot divide by zero in array division") - result = [a / b for a, b in zip(array1, array2)] + result = [a / b for a, b in zip(array1, array2, strict=True)]
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
app/agents/voice/automatic/prompts/system/charts.py(1 hunks)app/agents/voice/automatic/prompts/system/tool_scope.py(1 hunks)app/agents/voice/automatic/tools/__init__.py(2 hunks)app/agents/voice/automatic/tools/math/__init__.py(1 hunks)app/agents/voice/automatic/tools/math/math_operations.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.0)
app/agents/voice/automatic/tools/math/math_operations.py
21-21: Abstract raise to an inner function
(TRY301)
21-21: Avoid specifying long messages outside the exception class
(TRY003)
24-24: Abstract raise to an inner function
(TRY301)
24-24: Avoid specifying long messages outside the exception class
(TRY003)
30-30: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
30-30: Avoid specifying long messages outside the exception class
(TRY003)
38-38: Abstract raise to an inner function
(TRY301)
38-38: Avoid specifying long messages outside the exception class
(TRY003)
48-48: Abstract raise to an inner function
(TRY301)
48-48: Avoid specifying long messages outside the exception class
(TRY003)
50-50: Abstract raise to an inner function
(TRY301)
50-50: Avoid specifying long messages outside the exception class
(TRY003)
56-58: Abstract raise to an inner function
(TRY301)
56-58: Avoid specifying long messages outside the exception class
(TRY003)
63-65: Abstract raise to an inner function
(TRY301)
63-65: Avoid specifying long messages outside the exception class
(TRY003)
68-70: Abstract raise to an inner function
(TRY301)
68-70: Avoid specifying long messages outside the exception class
(TRY003)
74-76: Abstract raise to an inner function
(TRY301)
74-76: Avoid specifying long messages outside the exception class
(TRY003)
81-81: Abstract raise to an inner function
(TRY301)
81-81: Avoid specifying long messages outside the exception class
(TRY003)
83-83: Abstract raise to an inner function
(TRY301)
83-83: Avoid specifying long messages outside the exception class
(TRY003)
87-87: Abstract raise to an inner function
(TRY301)
87-87: Avoid specifying long messages outside the exception class
(TRY003)
90-90: Abstract raise to an inner function
(TRY301)
90-90: Avoid specifying long messages outside the exception class
(TRY003)
97-97: Do not catch blind exception: Exception
(BLE001)
113-113: Abstract raise to an inner function
(TRY301)
113-113: Avoid specifying long messages outside the exception class
(TRY003)
116-116: Abstract raise to an inner function
(TRY301)
116-116: Avoid specifying long messages outside the exception class
(TRY003)
122-122: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
122-122: Avoid specifying long messages outside the exception class
(TRY003)
132-132: Abstract raise to an inner function
(TRY301)
132-132: Avoid specifying long messages outside the exception class
(TRY003)
163-163: Abstract raise to an inner function
(TRY301)
163-163: Avoid specifying long messages outside the exception class
(TRY003)
175-175: Abstract raise to an inner function
(TRY301)
175-175: Avoid specifying long messages outside the exception class
(TRY003)
182-182: Do not catch blind exception: Exception
(BLE001)
197-197: Abstract raise to an inner function
(TRY301)
197-197: Avoid specifying long messages outside the exception class
(TRY003)
200-200: Abstract raise to an inner function
(TRY301)
200-200: Avoid specifying long messages outside the exception class
(TRY003)
206-206: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
206-206: Avoid specifying long messages outside the exception class
(TRY003)
213-213: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
213-213: Avoid specifying long messages outside the exception class
(TRY003)
219-219: Abstract raise to an inner function
(TRY301)
219-219: Avoid specifying long messages outside the exception class
(TRY003)
221-221: Abstract raise to an inner function
(TRY301)
221-221: Avoid specifying long messages outside the exception class
(TRY003)
222-222: zip() without an explicit strict= parameter
Add explicit value for parameter strict=
(B905)
225-225: Abstract raise to an inner function
(TRY301)
225-225: Avoid specifying long messages outside the exception class
(TRY003)
227-229: Abstract raise to an inner function
(TRY301)
227-229: Avoid specifying long messages outside the exception class
(TRY003)
240-240: Abstract raise to an inner function
(TRY301)
240-240: Avoid specifying long messages outside the exception class
(TRY003)
248-248: Abstract raise to an inner function
(TRY301)
248-248: Avoid specifying long messages outside the exception class
(TRY003)
250-250: Abstract raise to an inner function
(TRY301)
250-250: Avoid specifying long messages outside the exception class
(TRY003)
251-251: zip() without an explicit strict= parameter
Add explicit value for parameter strict=
(B905)
254-254: Abstract raise to an inner function
(TRY301)
254-254: Avoid specifying long messages outside the exception class
(TRY003)
256-256: Abstract raise to an inner function
(TRY301)
256-256: Avoid specifying long messages outside the exception class
(TRY003)
257-257: zip() without an explicit strict= parameter
Add explicit value for parameter strict=
(B905)
260-260: Abstract raise to an inner function
(TRY301)
260-260: Avoid specifying long messages outside the exception class
(TRY003)
262-262: Abstract raise to an inner function
(TRY301)
262-262: Avoid specifying long messages outside the exception class
(TRY003)
263-263: zip() without an explicit strict= parameter
Add explicit value for parameter strict=
(B905)
266-266: Abstract raise to an inner function
(TRY301)
266-266: Avoid specifying long messages outside the exception class
(TRY003)
268-268: Abstract raise to an inner function
(TRY301)
268-268: Avoid specifying long messages outside the exception class
(TRY003)
270-270: Abstract raise to an inner function
(TRY301)
270-270: Avoid specifying long messages outside the exception class
(TRY003)
271-271: zip() without an explicit strict= parameter
Add explicit value for parameter strict=
(B905)
273-273: Abstract raise to an inner function
(TRY301)
273-273: Avoid specifying long messages outside the exception class
(TRY003)
285-285: Do not catch blind exception: Exception
(BLE001)
app/agents/voice/automatic/tools/math/__init__.py
3-3: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
🔇 Additional comments (6)
app/agents/voice/automatic/tools/math/__init__.py (1)
1-3: LGTM!The module structure is clean and correctly exposes the math tools interface. The static analysis hint about sorting
__all__is a false positive—the list is already in alphabetical order.app/agents/voice/automatic/tools/math/math_operations.py (3)
12-100: LGTM!The arithmetic calculator implementation is comprehensive and correct. The validation logic properly handles edge cases like division by zero and negative square roots. The error handling ensures robust operation with clear error messages returned to the caller.
102-184: LGTM on the core logic!The sort and rank operations are well-implemented. The ranking algorithm correctly handles ties by assigning the same rank, and the percentile calculation uses proper linear interpolation. The mode operation's fallback for multiple modes is a good design choice.
290-398: LGTM!The function schemas are comprehensive and well-structured. The verbose descriptions with directives like "ALWAYS use this tool" are appropriate for LLM guidance and align with the usage in the system prompts. The tool_functions mapping correctly connects the schema names to their implementations.
app/agents/voice/automatic/prompts/system/charts.py (1)
78-78: LGTM!The update correctly references the new math tools by their proper names and aligns with the PR's objective of mandating tool usage for all calculations. This ensures consistency between the narration highlighting instructions and the available tooling.
app/agents/voice/automatic/tools/__init__.py (1)
15-16: LGTM!The math tools are correctly integrated into the initialization sequence. Loading them after system tools but before internet tools ensures they're available early in the tool chain. The logging provides good visibility into the number of math tools loaded.
Also applies to: 63-66
3c75a2b to
6373c10
Compare
| if not operation: | ||
| raise ValueError("Operation parameter is required") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enums are defined in schema, but your functions don’t rely on them directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The operation value is checked in ifelse as each will have a separate logic. Checking if it is part of the enum is redundant as it will throw unsupported action in ifelse anyways
| sorted_numbers = sorted(numbers) | ||
| n = len(sorted_numbers) | ||
| index = (percentile / 100) * (n - 1) | ||
| if index.is_integer(): | ||
| result = sorted_numbers[int(index)] | ||
| else: | ||
| lower = sorted_numbers[int(index)] | ||
| upper = sorted_numbers[int(index) + 1] | ||
| result = lower + (upper - lower) * (index - int(index)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if n == 1, your interpolation logic might index out of range
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, if n==1, it won't go to the else case. No Index out of range exception here
6373c10 to
e98871b
Compare
Added math tools to
Summary by CodeRabbit
New Features
Improvements