Skip to content

Commit 149999c

Browse files
committed
feat(tools): introduce @tools decorator for seamless function-to-tool conversion and automatic schema generation
Signed-off-by: OEvortex <abhat8283@gmail.com>
1 parent 17cad73 commit 149999c

File tree

1 file changed

+248
-1
lines changed

1 file changed

+248
-1
lines changed

README.md

Lines changed: 248 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ The official Python library for the [HelpingAI](https://helpingai.co) API - Adva
1010

1111
- **OpenAI-Compatible API**: Drop-in replacement with familiar interface
1212
- **Emotional Intelligence**: Advanced AI models with emotional understanding
13+
- **Tool Calling Made Easy**: [`@tools decorator`](HelpingAI/tools/core.py:144) for effortless function-to-tool conversion
14+
- **Automatic Schema Generation**: Type hint-based JSON schema creation with docstring parsing
15+
- **Universal Tool Compatibility**: Seamless integration with OpenAI-format tools
1316
- **Streaming Support**: Real-time response streaming
1417
- **Comprehensive Error Handling**: Detailed error types and retry mechanisms
1518
- **Type Safety**: Full type hints and IDE support
@@ -154,6 +157,238 @@ response = hai.chat.completions.create(
154157
hide_think=False # Show reasoning process
155158
)
156159
```
160+
## 🔧 Tool Calling with @tools Decorator
161+
162+
Transform any Python function into a powerful AI tool with zero boilerplate using the [`@tools`](HelpingAI/tools/core.py:144) decorator.
163+
164+
### Quick Start with Tools
165+
166+
```python
167+
from HelpingAI import HAI
168+
from HelpingAI.tools import tools, get_tools_format
169+
170+
@tools
171+
def get_weather(city: str, units: str = "celsius") -> str:
172+
"""Get current weather information for a city.
173+
174+
Args:
175+
city: The city name to get weather for
176+
units: Temperature units (celsius or fahrenheit)
177+
"""
178+
# Your weather API logic here
179+
return f"Weather in {city}: 22°{units[0].upper()}"
180+
181+
@tools
182+
def calculate_tip(bill_amount: float, tip_percentage: float = 15.0) -> dict:
183+
"""Calculate tip and total amount for a bill.
184+
185+
Args:
186+
bill_amount: The original bill amount
187+
tip_percentage: Tip percentage (default: 15.0)
188+
"""
189+
tip = bill_amount * (tip_percentage / 100)
190+
total = bill_amount + tip
191+
return {"tip": tip, "total": total, "original": bill_amount}
192+
193+
# Use with chat completions
194+
hai = HAI()
195+
response = hai.chat.completions.create(
196+
model="Helpingai3-raw",
197+
messages=[{"role": "user", "content": "What's the weather in Paris and calculate tip for $50 bill?"}],
198+
tools=get_tools_format() # Automatically includes all @tools functions
199+
)
200+
201+
print(response.choices[0].message.content)
202+
```
203+
204+
### Advanced Tool Features
205+
206+
#### Type System Support
207+
The [`@tools`](HelpingAI/tools/core.py:144) decorator automatically generates JSON schemas from Python type hints:
208+
209+
```python
210+
from typing import List, Optional, Union
211+
from enum import Enum
212+
213+
class Priority(Enum):
214+
LOW = "low"
215+
MEDIUM = "medium"
216+
HIGH = "high"
217+
218+
@tools
219+
def create_task(
220+
title: str,
221+
description: Optional[str] = None,
222+
priority: Priority = Priority.MEDIUM,
223+
tags: List[str] = None,
224+
due_date: Union[str, None] = None
225+
) -> dict:
226+
"""Create a new task with advanced type support.
227+
228+
Args:
229+
title: Task title
230+
description: Optional task description
231+
priority: Task priority level
232+
tags: List of task tags
233+
due_date: Due date in YYYY-MM-DD format
234+
"""
235+
return {
236+
"title": title,
237+
"description": description,
238+
"priority": priority.value,
239+
"tags": tags or [],
240+
"due_date": due_date
241+
}
242+
```
243+
244+
#### Tool Registry Management
245+
246+
```python
247+
from HelpingAI.tools import get_tools, get_registry, clear_registry
248+
249+
# Get specific tools
250+
weather_tools = get_tools(["get_weather", "calculate_tip"])
251+
252+
# Registry inspection
253+
registry = get_registry()
254+
print(f"Registered tools: {registry.list_tool_names()}")
255+
print(f"Total tools: {registry.size()}")
256+
257+
# Check if tool exists
258+
if registry.has_tool("get_weather"):
259+
weather_tool = registry.get_tool("get_weather")
260+
print(f"Tool: {weather_tool.name} - {weather_tool.description}")
261+
```
262+
263+
#### Universal Tool Compatibility
264+
265+
Seamlessly combine [`@tools`](HelpingAI/tools/core.py:144) functions with existing OpenAI-format tools:
266+
267+
```python
268+
from HelpingAI.tools import merge_tool_lists, ensure_tool_format
269+
270+
# Existing OpenAI-format tools
271+
legacy_tools = [{
272+
"type": "function",
273+
"function": {
274+
"name": "search_web",
275+
"description": "Search the web for information",
276+
"parameters": {
277+
"type": "object",
278+
"properties": {
279+
"query": {"type": "string", "description": "Search query"}
280+
},
281+
"required": ["query"]
282+
}
283+
}
284+
}]
285+
286+
# Combine with @tools functions
287+
combined_tools = merge_tool_lists(
288+
legacy_tools, # Existing tools
289+
get_tools_format(), # @tools functions
290+
"math" # Category name (if you have categorized tools)
291+
)
292+
293+
# Use in chat completion
294+
response = hai.chat.completions.create(
295+
model="Helpingai3-raw",
296+
messages=[{"role": "user", "content": "Help me with weather, calculations, and web search"}],
297+
tools=combined_tools
298+
)
299+
```
300+
301+
### Error Handling & Best Practices
302+
303+
```python
304+
from HelpingAI.tools import ToolExecutionError, SchemaValidationError, ToolRegistrationError
305+
306+
@tools
307+
def divide_numbers(a: float, b: float) -> float:
308+
"""Divide two numbers safely.
309+
310+
Args:
311+
a: The dividend
312+
b: The divisor
313+
"""
314+
if b == 0:
315+
raise ValueError("Cannot divide by zero")
316+
return a / b
317+
318+
# Handle tool execution in your application
319+
def execute_tool_safely(tool_name: str, arguments: dict):
320+
try:
321+
tool = get_registry().get_tool(tool_name)
322+
if not tool:
323+
return {"error": f"Tool '{tool_name}' not found"}
324+
325+
return tool.call(arguments)
326+
327+
except ToolExecutionError as e:
328+
print(f"Tool execution failed: {e}")
329+
return {"error": str(e)}
330+
except SchemaValidationError as e:
331+
print(f"Invalid arguments: {e}")
332+
return {"error": "Invalid parameters provided"}
333+
except ToolRegistrationError as e:
334+
print(f"Tool registration issue: {e}")
335+
return {"error": "Tool configuration error"}
336+
337+
# Example usage
338+
result = execute_tool_safely("divide_numbers", {"a": 10, "b": 2})
339+
print(result) # 5.0
340+
341+
error_result = execute_tool_safely("divide_numbers", {"a": 10, "b": 0})
342+
print(error_result) # {"error": "Cannot divide by zero"}
343+
```
344+
345+
### Migration from Legacy Tools
346+
347+
Transform your existing tool definitions with minimal effort:
348+
349+
**Before (Manual Schema):**
350+
```python
351+
tools = [{
352+
"type": "function",
353+
"function": {
354+
"name": "get_weather",
355+
"description": "Get weather information",
356+
"parameters": {
357+
"type": "object",
358+
"properties": {
359+
"city": {"type": "string", "description": "City name"},
360+
"units": {"type": "string", "description": "Temperature units", "enum": ["celsius", "fahrenheit"]}
361+
},
362+
"required": ["city"]
363+
}
364+
}
365+
}]
366+
```
367+
368+
**After (@tools Decorator):**
369+
```python
370+
from typing import Literal
371+
372+
@tools
373+
def get_weather(city: str, units: Literal["celsius", "fahrenheit"] = "celsius") -> str:
374+
"""Get weather information
375+
376+
Args:
377+
city: City name
378+
units: Temperature units
379+
"""
380+
# Implementation here
381+
pass
382+
```
383+
384+
The [`@tools`](HelpingAI/tools/core.py:144) decorator automatically:
385+
- ✅ Generates JSON schema from type hints
386+
- ✅ Extracts descriptions from docstrings
387+
- ✅ Handles required/optional parameters
388+
- ✅ Supports multiple docstring formats (Google, Sphinx, NumPy)
389+
- ✅ Provides comprehensive error handling
390+
- ✅ Maintains thread-safe tool registry
391+
157392

158393
## 📚 Documentation
159394

@@ -174,7 +409,14 @@ HelpingAI-python/
174409
│ ├── models.py # Model management
175410
│ ├── base_models.py # Data models
176411
│ ├── error.py # Exception classes
177-
│ └── version.py # Version information
412+
│ ├── version.py # Version information
413+
│ └── tools/ # Tool calling utilities
414+
│ ├── __init__.py # Tools module exports
415+
│ ├── core.py # @tools decorator and Fn class
416+
│ ├── schema.py # Automatic schema generation
417+
│ ├── registry.py # Tool registry management
418+
│ ├── compatibility.py # Format conversion utilities
419+
│ └── errors.py # Tool-specific exceptions
178420
├── docs/ # Documentation
179421
├── tests/ # Test suite
180422
├── setup.py # Package configuration
@@ -211,6 +453,11 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
211453

212454
## 🚀 What's New in v1.1.0
213455

456+
- **🔧 Tool Calling Framework**: New [`@tools decorator`](HelpingAI/tools/core.py:144) for effortless tool creation
457+
- **🤖 Automatic Schema Generation**: Type hint-based JSON schema creation with docstring parsing
458+
- **🔄 Universal Compatibility**: Seamless integration with existing OpenAI-format tools
459+
- **📝 Smart Documentation**: Multi-format docstring parsing (Google, Sphinx, NumPy styles)
460+
- **🛡️ Enhanced Tool Error Handling**: Comprehensive exception types for tool operations
214461
- **Extended Python Support**: Now supports Python 3.7-3.14
215462
- **Updated Models**: Support for latest models (Helpingai3-raw, Dhanishtha-2.0-preview)
216463
- **Dhanishtha-2.0 Integration**: World's first intermediate thinking model with multi-phase reasoning

0 commit comments

Comments
 (0)