chuk-tool-processor 0.2__py3-none-any.whl → 0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of chuk-tool-processor might be problematic. Click here for more details.
- chuk_tool_processor/execution/tool_executor.py +47 -9
- chuk_tool_processor/mcp/mcp_tool.py +46 -9
- chuk_tool_processor/mcp/setup_mcp_sse.py +21 -1
- chuk_tool_processor/mcp/stream_manager.py +95 -7
- chuk_tool_processor/mcp/transport/sse_transport.py +86 -13
- chuk_tool_processor-0.4.dist-info/METADATA +831 -0
- {chuk_tool_processor-0.2.dist-info → chuk_tool_processor-0.4.dist-info}/RECORD +9 -9
- chuk_tool_processor-0.2.dist-info/METADATA +0 -401
- {chuk_tool_processor-0.2.dist-info → chuk_tool_processor-0.4.dist-info}/WHEEL +0 -0
- {chuk_tool_processor-0.2.dist-info → chuk_tool_processor-0.4.dist-info}/top_level.txt +0 -0
|
@@ -3,7 +3,7 @@ chuk_tool_processor/core/__init__.py,sha256=slM7pZna88tyZrF3KtN22ApYyCqGNt5Yscv-
|
|
|
3
3
|
chuk_tool_processor/core/exceptions.py,sha256=h4zL1jpCY1Ud1wT8xDeMxZ8GR8ttmkObcv36peUHJEA,1571
|
|
4
4
|
chuk_tool_processor/core/processor.py,sha256=ttEYZTQHctXXiUP8gxAMCCSjbRvyOHojQe_UJezJYRs,18369
|
|
5
5
|
chuk_tool_processor/execution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
chuk_tool_processor/execution/tool_executor.py,sha256=
|
|
6
|
+
chuk_tool_processor/execution/tool_executor.py,sha256=SGnOrsQJ8b9dPD_2rYlRyp1WLcwn7pLfbrm5APOsQvo,14387
|
|
7
7
|
chuk_tool_processor/execution/strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
chuk_tool_processor/execution/strategies/inprocess_strategy.py,sha256=UJIv1g3Z9LpMsTYa9cqJB376StsI0up3cftH4OkqC2I,22582
|
|
9
9
|
chuk_tool_processor/execution/strategies/subprocess_strategy.py,sha256=Rb5GTffl-4dkAQG_zz8wjggqyWznVOr9gReLGHmE2io,22469
|
|
@@ -17,14 +17,14 @@ chuk_tool_processor/logging/formatter.py,sha256=RhlV6NqBYRBOtytDY49c9Y1J4l02ZjNX
|
|
|
17
17
|
chuk_tool_processor/logging/helpers.py,sha256=c1mS1sb_rh4bKG0hisyvT7l7cirQfXPSyWeBqmqALRw,5941
|
|
18
18
|
chuk_tool_processor/logging/metrics.py,sha256=s59Au8q0eqGGtJMDqmJBZhbJHh4BWGE1CzT0iI8lRS8,3624
|
|
19
19
|
chuk_tool_processor/mcp/__init__.py,sha256=vR9HHxLpXlKTIIwJJRr3QTmZegcdedR1YKyb46j6FIM,689
|
|
20
|
-
chuk_tool_processor/mcp/mcp_tool.py,sha256=
|
|
20
|
+
chuk_tool_processor/mcp/mcp_tool.py,sha256=a7WnBiu8DaSuZ8RI0Ums4M5A7v46RvijlqZa0020wWg,4922
|
|
21
21
|
chuk_tool_processor/mcp/register_mcp_tools.py,sha256=0q73gafC1d0ei_gqNidcUeY7NUg13UZdjhVOKEFcD5o,3642
|
|
22
|
-
chuk_tool_processor/mcp/setup_mcp_sse.py,sha256=
|
|
22
|
+
chuk_tool_processor/mcp/setup_mcp_sse.py,sha256=T0V27azQy06yc-RSc5uzEKyhbyAXFT-7O3pIn4k10HQ,3769
|
|
23
23
|
chuk_tool_processor/mcp/setup_mcp_stdio.py,sha256=P9qSgmxoNQbsOlGp83DlLLpN9BsG__MhlRsxFplNP3M,2753
|
|
24
|
-
chuk_tool_processor/mcp/stream_manager.py,sha256=
|
|
24
|
+
chuk_tool_processor/mcp/stream_manager.py,sha256=Wro1csV8S-V-PBan-4-c3cCyhJPmxG1wQJa4MLh02Dc,16914
|
|
25
25
|
chuk_tool_processor/mcp/transport/__init__.py,sha256=7QQqeSKVKv0N9GcyJuYF0R4FDZeooii5RjggvFFg5GY,296
|
|
26
26
|
chuk_tool_processor/mcp/transport/base_transport.py,sha256=1E29LjWw5vLQrPUDF_9TJt63P5dxAAN7n6E_KiZbGUY,3427
|
|
27
|
-
chuk_tool_processor/mcp/transport/sse_transport.py,sha256=
|
|
27
|
+
chuk_tool_processor/mcp/transport/sse_transport.py,sha256=2nyuc04Clc4FmJWxxZ2TmwiRd9NI7fpLqSN-g1wvRAI,19689
|
|
28
28
|
chuk_tool_processor/mcp/transport/stdio_transport.py,sha256=lFXL7p8ca4z_J0RBL8UCHrQ1UH7C2-LbC0tZhpya4V4,7763
|
|
29
29
|
chuk_tool_processor/models/__init__.py,sha256=TC__rdVa0lQsmJHM_hbLDPRgToa_pQT_UxRcPZk6iVw,40
|
|
30
30
|
chuk_tool_processor/models/execution_strategy.py,sha256=UVW35YIeMY2B3mpIKZD2rAkyOPayI6ckOOUALyf0YiQ,2115
|
|
@@ -52,7 +52,7 @@ chuk_tool_processor/registry/providers/__init__.py,sha256=eigwG_So11j7WbDGSWaKd3
|
|
|
52
52
|
chuk_tool_processor/registry/providers/memory.py,sha256=LlpPUU9E7S8Se6Q3VyKxLwpNm82SvmP8GLUmI8MkHxQ,5188
|
|
53
53
|
chuk_tool_processor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
chuk_tool_processor/utils/validation.py,sha256=fiTSsHq7zx-kyd755GaFCvPCa-EVasSpg0A1liNHkxU,4138
|
|
55
|
-
chuk_tool_processor-0.
|
|
56
|
-
chuk_tool_processor-0.
|
|
57
|
-
chuk_tool_processor-0.
|
|
58
|
-
chuk_tool_processor-0.
|
|
55
|
+
chuk_tool_processor-0.4.dist-info/METADATA,sha256=yk5rGA3xmEMCEZtikLNE508Q7oY1GwbTZR2jzOR2P5I,24312
|
|
56
|
+
chuk_tool_processor-0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
57
|
+
chuk_tool_processor-0.4.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
|
|
58
|
+
chuk_tool_processor-0.4.dist-info/RECORD,,
|
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: chuk-tool-processor
|
|
3
|
-
Version: 0.2
|
|
4
|
-
Summary: Add your description here
|
|
5
|
-
Requires-Python: >=3.11
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: chuk-mcp>=0.1.12
|
|
8
|
-
Requires-Dist: dotenv>=0.9.9
|
|
9
|
-
Requires-Dist: openai>=1.76.0
|
|
10
|
-
Requires-Dist: pydantic>=2.11.3
|
|
11
|
-
Requires-Dist: uuid>=1.30
|
|
12
|
-
|
|
13
|
-
# CHUK Tool Processor
|
|
14
|
-
|
|
15
|
-
An async-native framework for registering, discovering, and executing tools referenced in LLM responses.
|
|
16
|
-
|
|
17
|
-
## Quick Start
|
|
18
|
-
|
|
19
|
-
### Installation
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
# Clone the repository
|
|
23
|
-
git clone https://github.com/your-org/chuk-tool-processor.git
|
|
24
|
-
cd chuk-tool-processor
|
|
25
|
-
|
|
26
|
-
# Install with pip
|
|
27
|
-
pip install -e .
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Basic Usage
|
|
31
|
-
|
|
32
|
-
```python
|
|
33
|
-
import asyncio
|
|
34
|
-
from chuk_tool_processor.registry import register_tool, initialize
|
|
35
|
-
from chuk_tool_processor.models.tool_call import ToolCall
|
|
36
|
-
from chuk_tool_processor.execution.strategies.inprocess_strategy import InProcessStrategy
|
|
37
|
-
from chuk_tool_processor.execution.tool_executor import ToolExecutor
|
|
38
|
-
|
|
39
|
-
# Register a simple tool
|
|
40
|
-
@register_tool(name="calculator", description="Perform basic calculations")
|
|
41
|
-
class CalculatorTool:
|
|
42
|
-
async def execute(self, operation: str, x: float, y: float) -> dict:
|
|
43
|
-
if operation == "add":
|
|
44
|
-
result = x + y
|
|
45
|
-
elif operation == "multiply":
|
|
46
|
-
result = x * y
|
|
47
|
-
else:
|
|
48
|
-
raise ValueError(f"Unknown operation: {operation}")
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
"operation": operation,
|
|
52
|
-
"x": x,
|
|
53
|
-
"y": y,
|
|
54
|
-
"result": result
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
# Setup and execute tools
|
|
58
|
-
async def main():
|
|
59
|
-
# Initialize registry
|
|
60
|
-
await initialize()
|
|
61
|
-
|
|
62
|
-
# Get the default registry
|
|
63
|
-
from chuk_tool_processor.registry import get_default_registry
|
|
64
|
-
registry = await get_default_registry()
|
|
65
|
-
|
|
66
|
-
# Create execution strategy and executor
|
|
67
|
-
strategy = InProcessStrategy(registry)
|
|
68
|
-
executor = ToolExecutor(registry=registry, strategy=strategy)
|
|
69
|
-
|
|
70
|
-
# Create a tool call
|
|
71
|
-
call = ToolCall(
|
|
72
|
-
tool="calculator",
|
|
73
|
-
arguments={
|
|
74
|
-
"operation": "multiply",
|
|
75
|
-
"x": 5,
|
|
76
|
-
"y": 7
|
|
77
|
-
}
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
# Execute tool
|
|
81
|
-
results = await executor.execute([call])
|
|
82
|
-
|
|
83
|
-
# Display result
|
|
84
|
-
result = results[0]
|
|
85
|
-
if not result.error:
|
|
86
|
-
print(f"Result: {result.result}")
|
|
87
|
-
else:
|
|
88
|
-
print(f"Error: {result.error}")
|
|
89
|
-
|
|
90
|
-
if __name__ == "__main__":
|
|
91
|
-
asyncio.run(main())
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Core Features
|
|
95
|
-
|
|
96
|
-
### Async-Native Architecture
|
|
97
|
-
|
|
98
|
-
The entire framework is built with native `async/await` support, allowing for:
|
|
99
|
-
- Non-blocking execution of tools
|
|
100
|
-
- True concurrency with controlled parallelism
|
|
101
|
-
- Task-local context tracking across async boundaries
|
|
102
|
-
|
|
103
|
-
### Tool Registry
|
|
104
|
-
|
|
105
|
-
Tools are registered in a central registry with optional namespaces:
|
|
106
|
-
|
|
107
|
-
```python
|
|
108
|
-
# Register with default parameters
|
|
109
|
-
@register_tool()
|
|
110
|
-
class SimpleGreeter:
|
|
111
|
-
async def execute(self, name: str) -> str:
|
|
112
|
-
return f"Hello, {name}!"
|
|
113
|
-
|
|
114
|
-
# Register with custom name and namespace
|
|
115
|
-
@register_tool(name="weather", namespace="api", description="Get weather info")
|
|
116
|
-
class WeatherTool:
|
|
117
|
-
async def execute(self, location: str, units: str = "metric") -> dict:
|
|
118
|
-
# Implementation...
|
|
119
|
-
return {"temperature": 23.5, "conditions": "Sunny"}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Initialize and access the registry:
|
|
123
|
-
|
|
124
|
-
```python
|
|
125
|
-
# Initialize registry (required at startup)
|
|
126
|
-
await initialize()
|
|
127
|
-
|
|
128
|
-
# Get registry
|
|
129
|
-
registry = await get_default_registry()
|
|
130
|
-
|
|
131
|
-
# Look up a tool
|
|
132
|
-
tool = await registry.get_tool("weather", namespace="api")
|
|
133
|
-
|
|
134
|
-
# List registered tools
|
|
135
|
-
tools = await registry.list_tools()
|
|
136
|
-
|
|
137
|
-
# Get tool metadata
|
|
138
|
-
metadata = await registry.get_metadata("weather", namespace="api")
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### Execution Strategies
|
|
142
|
-
|
|
143
|
-
Two execution strategies are provided:
|
|
144
|
-
|
|
145
|
-
#### 1. InProcessStrategy
|
|
146
|
-
|
|
147
|
-
Executes tools in the same process with optional concurrency control:
|
|
148
|
-
|
|
149
|
-
```python
|
|
150
|
-
from chuk_tool_processor.execution.strategies.inprocess_strategy import InProcessStrategy
|
|
151
|
-
|
|
152
|
-
strategy = InProcessStrategy(
|
|
153
|
-
registry,
|
|
154
|
-
default_timeout=10.0, # Timeout for tool execution
|
|
155
|
-
max_concurrency=5 # Maximum concurrent executions
|
|
156
|
-
)
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
#### 2. SubprocessStrategy
|
|
160
|
-
|
|
161
|
-
Executes tools in separate processes for true isolation:
|
|
162
|
-
|
|
163
|
-
```python
|
|
164
|
-
from chuk_tool_processor.execution.strategies.subprocess_strategy import SubprocessStrategy
|
|
165
|
-
|
|
166
|
-
strategy = SubprocessStrategy(
|
|
167
|
-
registry,
|
|
168
|
-
max_workers=4, # Maximum worker processes
|
|
169
|
-
default_timeout=30.0 # Timeout for tool execution
|
|
170
|
-
)
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### Execution Wrappers
|
|
174
|
-
|
|
175
|
-
Enhance tool execution with optional wrappers:
|
|
176
|
-
|
|
177
|
-
#### Retry Logic
|
|
178
|
-
|
|
179
|
-
```python
|
|
180
|
-
from chuk_tool_processor.execution.wrappers.retry import RetryConfig, RetryableToolExecutor
|
|
181
|
-
|
|
182
|
-
# Use as a wrapper
|
|
183
|
-
retry_executor = RetryableToolExecutor(
|
|
184
|
-
executor=base_executor,
|
|
185
|
-
default_config=RetryConfig(
|
|
186
|
-
max_retries=3,
|
|
187
|
-
base_delay=0.5,
|
|
188
|
-
jitter=True
|
|
189
|
-
)
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
# Or as a decorator
|
|
193
|
-
from chuk_tool_processor.execution.wrappers.retry import retryable
|
|
194
|
-
|
|
195
|
-
@retryable(max_retries=3, base_delay=0.5)
|
|
196
|
-
@register_tool(name="flaky_api")
|
|
197
|
-
class FlakyApiTool:
|
|
198
|
-
async def execute(self, query: str) -> dict:
|
|
199
|
-
# Implementation with potential failures
|
|
200
|
-
pass
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
#### Caching
|
|
204
|
-
|
|
205
|
-
```python
|
|
206
|
-
from chuk_tool_processor.execution.wrappers.caching import InMemoryCache, CachingToolExecutor
|
|
207
|
-
|
|
208
|
-
# Use as a wrapper
|
|
209
|
-
cache = InMemoryCache(default_ttl=60) # 60 second TTL
|
|
210
|
-
cache_executor = CachingToolExecutor(
|
|
211
|
-
executor=base_executor,
|
|
212
|
-
cache=cache
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
# Or as a decorator
|
|
216
|
-
from chuk_tool_processor.execution.wrappers.caching import cacheable
|
|
217
|
-
|
|
218
|
-
@cacheable(ttl=300) # Cache for 5 minutes
|
|
219
|
-
@register_tool(name="expensive_operation")
|
|
220
|
-
class ExpensiveOperationTool:
|
|
221
|
-
async def execute(self, input_value: int) -> dict:
|
|
222
|
-
# Expensive computation
|
|
223
|
-
pass
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
#### Rate Limiting
|
|
227
|
-
|
|
228
|
-
```python
|
|
229
|
-
from chuk_tool_processor.execution.wrappers.rate_limiting import RateLimiter, RateLimitedToolExecutor
|
|
230
|
-
|
|
231
|
-
# Use as a wrapper
|
|
232
|
-
limiter = RateLimiter(global_limit=100, global_period=60.0) # 100 requests per minute
|
|
233
|
-
rate_limited_executor = RateLimitedToolExecutor(
|
|
234
|
-
executor=base_executor,
|
|
235
|
-
limiter=limiter
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
# Or as a decorator
|
|
239
|
-
from chuk_tool_processor.execution.wrappers.rate_limiting import rate_limited
|
|
240
|
-
|
|
241
|
-
@rate_limited(limit=5, period=60.0) # 5 requests per minute
|
|
242
|
-
@register_tool(name="external_api")
|
|
243
|
-
class ExternalApiTool:
|
|
244
|
-
async def execute(self, query: str) -> dict:
|
|
245
|
-
# Call to rate-limited external API
|
|
246
|
-
pass
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### Streaming Tool Support
|
|
250
|
-
|
|
251
|
-
Tools can stream results incrementally:
|
|
252
|
-
|
|
253
|
-
```python
|
|
254
|
-
from chuk_tool_processor.models.streaming_tool import StreamingTool
|
|
255
|
-
from pydantic import BaseModel, Field
|
|
256
|
-
from typing import AsyncIterator
|
|
257
|
-
|
|
258
|
-
@register_tool(name="counter")
|
|
259
|
-
class CounterTool(StreamingTool):
|
|
260
|
-
"""Stream incremental counts."""
|
|
261
|
-
|
|
262
|
-
class Arguments(BaseModel):
|
|
263
|
-
start: int = Field(1, description="Starting value")
|
|
264
|
-
end: int = Field(10, description="Ending value")
|
|
265
|
-
delay: float = Field(0.5, description="Delay between items")
|
|
266
|
-
|
|
267
|
-
class Result(BaseModel):
|
|
268
|
-
value: int
|
|
269
|
-
timestamp: str
|
|
270
|
-
|
|
271
|
-
async def _stream_execute(self, start: int, end: int, delay: float) -> AsyncIterator[Result]:
|
|
272
|
-
"""Stream each count with a delay."""
|
|
273
|
-
from datetime import datetime
|
|
274
|
-
|
|
275
|
-
for i in range(start, end + 1):
|
|
276
|
-
await asyncio.sleep(delay)
|
|
277
|
-
yield self.Result(
|
|
278
|
-
value=i,
|
|
279
|
-
timestamp=datetime.now().isoformat()
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
# Stream results
|
|
283
|
-
async for result in executor.stream_execute([tool_call]):
|
|
284
|
-
print(f"Received: {result.result.value}")
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Comprehensive Error Handling
|
|
288
|
-
|
|
289
|
-
Errors are captured in the result objects rather than raising exceptions:
|
|
290
|
-
|
|
291
|
-
```python
|
|
292
|
-
# Execute tool calls
|
|
293
|
-
results = await executor.execute([call1, call2, call3])
|
|
294
|
-
|
|
295
|
-
for result in results:
|
|
296
|
-
if result.error:
|
|
297
|
-
print(f"Tool {result.tool} failed: {result.error}")
|
|
298
|
-
print(f"Duration: {(result.end_time - result.start_time).total_seconds()}s")
|
|
299
|
-
else:
|
|
300
|
-
print(f"Tool {result.tool} succeeded: {result.result}")
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### Validation
|
|
304
|
-
|
|
305
|
-
Validate tool arguments and results:
|
|
306
|
-
|
|
307
|
-
```python
|
|
308
|
-
from pydantic import BaseModel
|
|
309
|
-
from chuk_tool_processor.models.validated_tool import ValidatedTool
|
|
310
|
-
|
|
311
|
-
@register_tool(name="validate_data", namespace="utils")
|
|
312
|
-
class ValidatedDataTool(ValidatedTool):
|
|
313
|
-
class Arguments(BaseModel):
|
|
314
|
-
username: str
|
|
315
|
-
age: int
|
|
316
|
-
email: str
|
|
317
|
-
|
|
318
|
-
class Result(BaseModel):
|
|
319
|
-
is_valid: bool
|
|
320
|
-
errors: list[str] = []
|
|
321
|
-
|
|
322
|
-
async def _execute(self, username: str, age: int, email: str) -> Result:
|
|
323
|
-
errors = []
|
|
324
|
-
|
|
325
|
-
if len(username) < 3:
|
|
326
|
-
errors.append("Username too short")
|
|
327
|
-
|
|
328
|
-
if age < 18:
|
|
329
|
-
errors.append("Must be 18 or older")
|
|
330
|
-
|
|
331
|
-
if "@" not in email:
|
|
332
|
-
errors.append("Invalid email")
|
|
333
|
-
|
|
334
|
-
return self.Result(
|
|
335
|
-
is_valid=len(errors) == 0,
|
|
336
|
-
errors=errors
|
|
337
|
-
)
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
## Processing LLM Responses
|
|
341
|
-
|
|
342
|
-
The `ToolProcessor` helps extract and execute tool calls from LLM responses:
|
|
343
|
-
|
|
344
|
-
```python
|
|
345
|
-
from chuk_tool_processor.core.processor import ToolProcessor
|
|
346
|
-
|
|
347
|
-
# Create processor
|
|
348
|
-
processor = ToolProcessor()
|
|
349
|
-
await processor.initialize()
|
|
350
|
-
|
|
351
|
-
# Process text with tool calls
|
|
352
|
-
llm_output = """
|
|
353
|
-
I'll help calculate that for you.
|
|
354
|
-
|
|
355
|
-
<tool name="calculator" args='{"operation": "multiply", "x": 5, "y": 7}'/>
|
|
356
|
-
|
|
357
|
-
The result should be 35.
|
|
358
|
-
"""
|
|
359
|
-
|
|
360
|
-
# Extract and execute tool calls
|
|
361
|
-
results = await processor.process_text(llm_output)
|
|
362
|
-
|
|
363
|
-
# Process results
|
|
364
|
-
for result in results:
|
|
365
|
-
print(f"Tool: {result.tool}")
|
|
366
|
-
print(f"Result: {result.result}")
|
|
367
|
-
print(f"Error: {result.error}")
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
The processor supports various formats:
|
|
371
|
-
|
|
372
|
-
```python
|
|
373
|
-
# XML format
|
|
374
|
-
<tool name="calculator" args='{"operation": "add", "x": 5, "y": 3}'/>
|
|
375
|
-
|
|
376
|
-
# OpenAI function call format
|
|
377
|
-
{
|
|
378
|
-
"function_call": {
|
|
379
|
-
"name": "calculator",
|
|
380
|
-
"arguments": "{\"operation\": \"add\", \"x\": 5, \"y\": 3}"
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
# JSON format
|
|
385
|
-
{
|
|
386
|
-
"tool_calls": [
|
|
387
|
-
{
|
|
388
|
-
"id": "call_123",
|
|
389
|
-
"type": "function",
|
|
390
|
-
"function": {
|
|
391
|
-
"name": "calculator",
|
|
392
|
-
"arguments": "{\"operation\": \"add\", \"x\": 5, \"y\": 3}"
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
]
|
|
396
|
-
}
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
## License
|
|
400
|
-
|
|
401
|
-
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
File without changes
|
|
File without changes
|