selectools 0.2.0__tar.gz → 0.3.0__tar.gz
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.
- {selectools-0.2.0/src/selectools.egg-info → selectools-0.3.0}/PKG-INFO +29 -29
- {selectools-0.2.0 → selectools-0.3.0}/README.md +27 -27
- {selectools-0.2.0 → selectools-0.3.0}/pyproject.toml +4 -4
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/__init__.py +1 -1
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/cli.py +5 -5
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/examples/bbox.py +1 -1
- {selectools-0.2.0 → selectools-0.3.0/src/selectools.egg-info}/PKG-INFO +29 -29
- selectools-0.3.0/src/selectools.egg-info/SOURCES.txt +22 -0
- selectools-0.3.0/src/selectools.egg-info/entry_points.txt +2 -0
- selectools-0.3.0/src/selectools.egg-info/top_level.txt +1 -0
- {selectools-0.2.0 → selectools-0.3.0}/tests/test_framework.py +7 -7
- selectools-0.2.0/src/selectools.egg-info/SOURCES.txt +0 -22
- selectools-0.2.0/src/selectools.egg-info/entry_points.txt +0 -2
- selectools-0.2.0/src/selectools.egg-info/top_level.txt +0 -1
- {selectools-0.2.0 → selectools-0.3.0}/LICENSE +0 -0
- {selectools-0.2.0 → selectools-0.3.0}/setup.cfg +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/agent.py +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/env.py +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/parser.py +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/prompt.py +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/providers/base.py +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/providers/openai_provider.py +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/providers/stubs.py +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/tools.py +0 -0
- {selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/types.py +0 -0
- {selectools-0.2.0 → selectools-0.3.0}/src/selectools.egg-info/dependency_links.txt +0 -0
- {selectools-0.2.0 → selectools-0.3.0}/src/selectools.egg-info/requires.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: selectools
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Build AI agents that call your custom Python functions. Connect LLMs to tools, APIs, and databases with any provider (OpenAI, Anthropic, Gemini).
|
|
5
5
|
Author-email: Backtrack <engineering@backtrack.app>
|
|
6
6
|
License: LGPL-3.0-or-later
|
|
7
7
|
Project-URL: Homepage, https://github.com/johnnichev/selectools
|
|
@@ -33,13 +33,13 @@ Requires-Dist: anthropic<1.0.0,>=0.28.0; extra == "providers"
|
|
|
33
33
|
Requires-Dist: google-generativeai<1.0.0,>=0.8.3; extra == "providers"
|
|
34
34
|
Dynamic: license-file
|
|
35
35
|
|
|
36
|
-
# AI Tool Calling
|
|
36
|
+
# AI Tool Calling - Selectools
|
|
37
37
|
|
|
38
38
|
[](https://badge.fury.io/py/selectools)
|
|
39
39
|
[](https://www.gnu.org/licenses/lgpl-3.0)
|
|
40
40
|
[](https://www.python.org/downloads/)
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
**Build AI agents that can call your custom Python functions.** Selectools lets you connect LLMs (OpenAI, Anthropic, Gemini) to your own tools and functions. Define what your agent can do—search databases, call APIs, process images, or anything else—and let the LLM decide when and how to use them. Works with any provider, handles errors gracefully, and includes streaming support.
|
|
43
43
|
|
|
44
44
|
## Why This Library Stands Out
|
|
45
45
|
|
|
@@ -73,7 +73,7 @@ Built for real-world reliability:
|
|
|
73
73
|
### 🧪 **Testing-Friendly Architecture**
|
|
74
74
|
|
|
75
75
|
- **Local provider** for offline development and testing (no API calls, no costs)
|
|
76
|
-
- **Mock injection** for deterministic testing (e.g., `
|
|
76
|
+
- **Mock injection** for deterministic testing (e.g., `SELECTOOLS_BBOX_MOCK_JSON`)
|
|
77
77
|
- **Fake providers** included for unit testing your agent logic
|
|
78
78
|
- Clean separation of concerns makes components easy to test in isolation
|
|
79
79
|
|
|
@@ -83,7 +83,7 @@ Not a framework that takes over your application—a library that integrates int
|
|
|
83
83
|
|
|
84
84
|
## What's Included
|
|
85
85
|
|
|
86
|
-
- Core package at `src/
|
|
86
|
+
- Core package at `src/selectools/` with agent loop, parser, prompt builder, and provider adapters
|
|
87
87
|
- Providers: OpenAI plus Anthropic/Gemini/Local sharing the same interface
|
|
88
88
|
- Library-first examples (see below) and tests with fake providers for schemas, parsing, agent wiring
|
|
89
89
|
- PyPI-ready metadata (`pyproject.toml`) using a src-layout package
|
|
@@ -124,8 +124,8 @@ export GEMINI_API_KEY="your-api-key-here" # Optional
|
|
|
124
124
|
## Usage (Library)
|
|
125
125
|
|
|
126
126
|
```python
|
|
127
|
-
from
|
|
128
|
-
from
|
|
127
|
+
from selectools import Agent, AgentConfig, Message, Role, Tool, ToolParameter
|
|
128
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
129
129
|
|
|
130
130
|
# Define a tool
|
|
131
131
|
search_tool = Tool(
|
|
@@ -145,7 +145,7 @@ print(response.content)
|
|
|
145
145
|
|
|
146
146
|
- Define tools (`Tool` or `@tool`/`ToolRegistry`), pick a provider, run `Agent.run([...])`.
|
|
147
147
|
- Add vision by supplying `image_path` on `Message` when the provider supports it.
|
|
148
|
-
- For offline/testing: use the Local provider and/or `
|
|
148
|
+
- For offline/testing: use the Local provider and/or `SELECTOOLS_BBOX_MOCK_JSON=tests/fixtures/bbox_mock.json`.
|
|
149
149
|
- Optional dev helpers (not required for library use): `scripts/smoke_cli.py` for quick provider smokes; `scripts/chat.py` for the vision demo.
|
|
150
150
|
|
|
151
151
|
## Providers (incl. vision & limits)
|
|
@@ -171,8 +171,8 @@ print(response.content)
|
|
|
171
171
|
The simplest possible tool—great for testing your setup:
|
|
172
172
|
|
|
173
173
|
```python
|
|
174
|
-
from
|
|
175
|
-
from
|
|
174
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
175
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
176
176
|
|
|
177
177
|
@tool(description="Echo input back to user")
|
|
178
178
|
def echo(text: str) -> str:
|
|
@@ -188,8 +188,8 @@ print(resp.content)
|
|
|
188
188
|
Build a customer support agent that can search a knowledge base, check order status, and create tickets:
|
|
189
189
|
|
|
190
190
|
```python
|
|
191
|
-
from
|
|
192
|
-
from
|
|
191
|
+
from selectools import Agent, AgentConfig, Message, Role, ToolRegistry
|
|
192
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
193
193
|
import json
|
|
194
194
|
|
|
195
195
|
registry = ToolRegistry()
|
|
@@ -241,9 +241,9 @@ print(response.content)
|
|
|
241
241
|
Detect and annotate objects in images using OpenAI Vision:
|
|
242
242
|
|
|
243
243
|
```python
|
|
244
|
-
from
|
|
245
|
-
from
|
|
246
|
-
from
|
|
244
|
+
from selectools import Agent, AgentConfig, Message, Role
|
|
245
|
+
from selectools.examples.bbox import create_bounding_box_tool
|
|
246
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
247
247
|
|
|
248
248
|
bbox_tool = create_bounding_box_tool()
|
|
249
249
|
agent = Agent(
|
|
@@ -269,8 +269,8 @@ print(response.content)
|
|
|
269
269
|
Chain multiple tools to research a topic, summarize findings, and save results:
|
|
270
270
|
|
|
271
271
|
```python
|
|
272
|
-
from
|
|
273
|
-
from
|
|
272
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
273
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
274
274
|
import json
|
|
275
275
|
|
|
276
276
|
@tool(description="Search academic papers and articles")
|
|
@@ -315,8 +315,8 @@ print(response.content)
|
|
|
315
315
|
Build responsive UIs with streaming responses:
|
|
316
316
|
|
|
317
317
|
```python
|
|
318
|
-
from
|
|
319
|
-
from
|
|
318
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
319
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
320
320
|
import sys
|
|
321
321
|
|
|
322
322
|
@tool(description="Get current time in a timezone")
|
|
@@ -348,9 +348,9 @@ print("\n") # Newline after streaming completes
|
|
|
348
348
|
Keep sensitive credentials out of tool signatures using `injected_kwargs`:
|
|
349
349
|
|
|
350
350
|
```python
|
|
351
|
-
from
|
|
352
|
-
from
|
|
353
|
-
from
|
|
351
|
+
from selectools import Agent, AgentConfig, Message, Role, Tool
|
|
352
|
+
from selectools.tools import ToolParameter
|
|
353
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
354
354
|
import psycopg2
|
|
355
355
|
|
|
356
356
|
def query_database(sql: str, db_connection) -> str:
|
|
@@ -398,8 +398,8 @@ print(response.content)
|
|
|
398
398
|
Develop and test without API calls using the Local provider:
|
|
399
399
|
|
|
400
400
|
```python
|
|
401
|
-
from
|
|
402
|
-
from
|
|
401
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
402
|
+
from selectools.providers.stubs import LocalProvider
|
|
403
403
|
|
|
404
404
|
@tool(description="Format a todo item with priority")
|
|
405
405
|
def create_todo(task: str, priority: str = "medium", due_date: str = None) -> str:
|
|
@@ -425,10 +425,10 @@ print(response.content)
|
|
|
425
425
|
Switch between providers without changing your tool definitions:
|
|
426
426
|
|
|
427
427
|
```python
|
|
428
|
-
from
|
|
429
|
-
from
|
|
430
|
-
from
|
|
431
|
-
from
|
|
428
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
429
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
430
|
+
from selectools.providers.anthropic_provider import AnthropicProvider
|
|
431
|
+
from selectools.providers.gemini_provider import GeminiProvider
|
|
432
432
|
import os
|
|
433
433
|
|
|
434
434
|
@tool(description="Calculate compound interest")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# AI Tool Calling
|
|
1
|
+
# AI Tool Calling - Selectools
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/py/selectools)
|
|
4
4
|
[](https://www.gnu.org/licenses/lgpl-3.0)
|
|
5
5
|
[](https://www.python.org/downloads/)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Build AI agents that can call your custom Python functions.** Selectools lets you connect LLMs (OpenAI, Anthropic, Gemini) to your own tools and functions. Define what your agent can do—search databases, call APIs, process images, or anything else—and let the LLM decide when and how to use them. Works with any provider, handles errors gracefully, and includes streaming support.
|
|
8
8
|
|
|
9
9
|
## Why This Library Stands Out
|
|
10
10
|
|
|
@@ -38,7 +38,7 @@ Built for real-world reliability:
|
|
|
38
38
|
### 🧪 **Testing-Friendly Architecture**
|
|
39
39
|
|
|
40
40
|
- **Local provider** for offline development and testing (no API calls, no costs)
|
|
41
|
-
- **Mock injection** for deterministic testing (e.g., `
|
|
41
|
+
- **Mock injection** for deterministic testing (e.g., `SELECTOOLS_BBOX_MOCK_JSON`)
|
|
42
42
|
- **Fake providers** included for unit testing your agent logic
|
|
43
43
|
- Clean separation of concerns makes components easy to test in isolation
|
|
44
44
|
|
|
@@ -48,7 +48,7 @@ Not a framework that takes over your application—a library that integrates int
|
|
|
48
48
|
|
|
49
49
|
## What's Included
|
|
50
50
|
|
|
51
|
-
- Core package at `src/
|
|
51
|
+
- Core package at `src/selectools/` with agent loop, parser, prompt builder, and provider adapters
|
|
52
52
|
- Providers: OpenAI plus Anthropic/Gemini/Local sharing the same interface
|
|
53
53
|
- Library-first examples (see below) and tests with fake providers for schemas, parsing, agent wiring
|
|
54
54
|
- PyPI-ready metadata (`pyproject.toml`) using a src-layout package
|
|
@@ -89,8 +89,8 @@ export GEMINI_API_KEY="your-api-key-here" # Optional
|
|
|
89
89
|
## Usage (Library)
|
|
90
90
|
|
|
91
91
|
```python
|
|
92
|
-
from
|
|
93
|
-
from
|
|
92
|
+
from selectools import Agent, AgentConfig, Message, Role, Tool, ToolParameter
|
|
93
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
94
94
|
|
|
95
95
|
# Define a tool
|
|
96
96
|
search_tool = Tool(
|
|
@@ -110,7 +110,7 @@ print(response.content)
|
|
|
110
110
|
|
|
111
111
|
- Define tools (`Tool` or `@tool`/`ToolRegistry`), pick a provider, run `Agent.run([...])`.
|
|
112
112
|
- Add vision by supplying `image_path` on `Message` when the provider supports it.
|
|
113
|
-
- For offline/testing: use the Local provider and/or `
|
|
113
|
+
- For offline/testing: use the Local provider and/or `SELECTOOLS_BBOX_MOCK_JSON=tests/fixtures/bbox_mock.json`.
|
|
114
114
|
- Optional dev helpers (not required for library use): `scripts/smoke_cli.py` for quick provider smokes; `scripts/chat.py` for the vision demo.
|
|
115
115
|
|
|
116
116
|
## Providers (incl. vision & limits)
|
|
@@ -136,8 +136,8 @@ print(response.content)
|
|
|
136
136
|
The simplest possible tool—great for testing your setup:
|
|
137
137
|
|
|
138
138
|
```python
|
|
139
|
-
from
|
|
140
|
-
from
|
|
139
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
140
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
141
141
|
|
|
142
142
|
@tool(description="Echo input back to user")
|
|
143
143
|
def echo(text: str) -> str:
|
|
@@ -153,8 +153,8 @@ print(resp.content)
|
|
|
153
153
|
Build a customer support agent that can search a knowledge base, check order status, and create tickets:
|
|
154
154
|
|
|
155
155
|
```python
|
|
156
|
-
from
|
|
157
|
-
from
|
|
156
|
+
from selectools import Agent, AgentConfig, Message, Role, ToolRegistry
|
|
157
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
158
158
|
import json
|
|
159
159
|
|
|
160
160
|
registry = ToolRegistry()
|
|
@@ -206,9 +206,9 @@ print(response.content)
|
|
|
206
206
|
Detect and annotate objects in images using OpenAI Vision:
|
|
207
207
|
|
|
208
208
|
```python
|
|
209
|
-
from
|
|
210
|
-
from
|
|
211
|
-
from
|
|
209
|
+
from selectools import Agent, AgentConfig, Message, Role
|
|
210
|
+
from selectools.examples.bbox import create_bounding_box_tool
|
|
211
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
212
212
|
|
|
213
213
|
bbox_tool = create_bounding_box_tool()
|
|
214
214
|
agent = Agent(
|
|
@@ -234,8 +234,8 @@ print(response.content)
|
|
|
234
234
|
Chain multiple tools to research a topic, summarize findings, and save results:
|
|
235
235
|
|
|
236
236
|
```python
|
|
237
|
-
from
|
|
238
|
-
from
|
|
237
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
238
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
239
239
|
import json
|
|
240
240
|
|
|
241
241
|
@tool(description="Search academic papers and articles")
|
|
@@ -280,8 +280,8 @@ print(response.content)
|
|
|
280
280
|
Build responsive UIs with streaming responses:
|
|
281
281
|
|
|
282
282
|
```python
|
|
283
|
-
from
|
|
284
|
-
from
|
|
283
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
284
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
285
285
|
import sys
|
|
286
286
|
|
|
287
287
|
@tool(description="Get current time in a timezone")
|
|
@@ -313,9 +313,9 @@ print("\n") # Newline after streaming completes
|
|
|
313
313
|
Keep sensitive credentials out of tool signatures using `injected_kwargs`:
|
|
314
314
|
|
|
315
315
|
```python
|
|
316
|
-
from
|
|
317
|
-
from
|
|
318
|
-
from
|
|
316
|
+
from selectools import Agent, AgentConfig, Message, Role, Tool
|
|
317
|
+
from selectools.tools import ToolParameter
|
|
318
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
319
319
|
import psycopg2
|
|
320
320
|
|
|
321
321
|
def query_database(sql: str, db_connection) -> str:
|
|
@@ -363,8 +363,8 @@ print(response.content)
|
|
|
363
363
|
Develop and test without API calls using the Local provider:
|
|
364
364
|
|
|
365
365
|
```python
|
|
366
|
-
from
|
|
367
|
-
from
|
|
366
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
367
|
+
from selectools.providers.stubs import LocalProvider
|
|
368
368
|
|
|
369
369
|
@tool(description="Format a todo item with priority")
|
|
370
370
|
def create_todo(task: str, priority: str = "medium", due_date: str = None) -> str:
|
|
@@ -390,10 +390,10 @@ print(response.content)
|
|
|
390
390
|
Switch between providers without changing your tool definitions:
|
|
391
391
|
|
|
392
392
|
```python
|
|
393
|
-
from
|
|
394
|
-
from
|
|
395
|
-
from
|
|
396
|
-
from
|
|
393
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
394
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
395
|
+
from selectools.providers.anthropic_provider import AnthropicProvider
|
|
396
|
+
from selectools.providers.gemini_provider import GeminiProvider
|
|
397
397
|
import os
|
|
398
398
|
|
|
399
399
|
@tool(description="Calculate compound interest")
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "selectools"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Build AI agents that call your custom Python functions. Connect LLMs to tools, APIs, and databases with any provider (OpenAI, Anthropic, Gemini)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
license = {text = "LGPL-3.0-or-later"}
|
|
@@ -39,8 +39,8 @@ dev = ["pytest>=7.0.0", "build>=1.2.1", "twine>=5.0.0"]
|
|
|
39
39
|
providers = ["anthropic>=0.28.0,<1.0.0", "google-generativeai>=0.8.3,<1.0.0"]
|
|
40
40
|
|
|
41
41
|
[project.scripts]
|
|
42
|
-
|
|
42
|
+
selectools = "selectools.cli:main"
|
|
43
43
|
|
|
44
44
|
[tool.setuptools]
|
|
45
45
|
package-dir = {"" = "src"}
|
|
46
|
-
packages = ["
|
|
46
|
+
packages = ["selectools", "selectools.providers", "selectools.examples"]
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
|
-
CLI entrypoint for the
|
|
2
|
+
CLI entrypoint for the selectools library.
|
|
3
3
|
|
|
4
4
|
Examples:
|
|
5
|
-
python -m
|
|
6
|
-
python -m
|
|
7
|
-
python -m
|
|
5
|
+
python -m selectools.cli list-tools
|
|
6
|
+
python -m selectools.cli run --provider openai --model gpt-4o --prompt "Search docs" --tool echo
|
|
7
|
+
python -m selectools.cli run --provider openai --prompt "Find the object" --image assets/environment.png --tool detect_bounding_box
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
@@ -132,7 +132,7 @@ def interactive_chat(args, tools: Dict[str, Tool]) -> None:
|
|
|
132
132
|
|
|
133
133
|
|
|
134
134
|
def build_parser() -> argparse.ArgumentParser:
|
|
135
|
-
parser = argparse.ArgumentParser(description="Multi-model
|
|
135
|
+
parser = argparse.ArgumentParser(description="Multi-model selectools CLI")
|
|
136
136
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
137
137
|
|
|
138
138
|
list_parser = subparsers.add_parser("list-tools", help="List available tools")
|
|
@@ -18,7 +18,7 @@ from ..tools import Tool, ToolParameter
|
|
|
18
18
|
|
|
19
19
|
PROJECT_ROOT = Path(__file__).resolve().parents[3]
|
|
20
20
|
ASSETS_DIR = PROJECT_ROOT / "assets"
|
|
21
|
-
BBOX_MOCK_ENV = "
|
|
21
|
+
BBOX_MOCK_ENV = "SELECTOOLS_BBOX_MOCK_JSON"
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def _resolve_image_path(image_path: str) -> Path:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: selectools
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Build AI agents that call your custom Python functions. Connect LLMs to tools, APIs, and databases with any provider (OpenAI, Anthropic, Gemini).
|
|
5
5
|
Author-email: Backtrack <engineering@backtrack.app>
|
|
6
6
|
License: LGPL-3.0-or-later
|
|
7
7
|
Project-URL: Homepage, https://github.com/johnnichev/selectools
|
|
@@ -33,13 +33,13 @@ Requires-Dist: anthropic<1.0.0,>=0.28.0; extra == "providers"
|
|
|
33
33
|
Requires-Dist: google-generativeai<1.0.0,>=0.8.3; extra == "providers"
|
|
34
34
|
Dynamic: license-file
|
|
35
35
|
|
|
36
|
-
# AI Tool Calling
|
|
36
|
+
# AI Tool Calling - Selectools
|
|
37
37
|
|
|
38
38
|
[](https://badge.fury.io/py/selectools)
|
|
39
39
|
[](https://www.gnu.org/licenses/lgpl-3.0)
|
|
40
40
|
[](https://www.python.org/downloads/)
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
**Build AI agents that can call your custom Python functions.** Selectools lets you connect LLMs (OpenAI, Anthropic, Gemini) to your own tools and functions. Define what your agent can do—search databases, call APIs, process images, or anything else—and let the LLM decide when and how to use them. Works with any provider, handles errors gracefully, and includes streaming support.
|
|
43
43
|
|
|
44
44
|
## Why This Library Stands Out
|
|
45
45
|
|
|
@@ -73,7 +73,7 @@ Built for real-world reliability:
|
|
|
73
73
|
### 🧪 **Testing-Friendly Architecture**
|
|
74
74
|
|
|
75
75
|
- **Local provider** for offline development and testing (no API calls, no costs)
|
|
76
|
-
- **Mock injection** for deterministic testing (e.g., `
|
|
76
|
+
- **Mock injection** for deterministic testing (e.g., `SELECTOOLS_BBOX_MOCK_JSON`)
|
|
77
77
|
- **Fake providers** included for unit testing your agent logic
|
|
78
78
|
- Clean separation of concerns makes components easy to test in isolation
|
|
79
79
|
|
|
@@ -83,7 +83,7 @@ Not a framework that takes over your application—a library that integrates int
|
|
|
83
83
|
|
|
84
84
|
## What's Included
|
|
85
85
|
|
|
86
|
-
- Core package at `src/
|
|
86
|
+
- Core package at `src/selectools/` with agent loop, parser, prompt builder, and provider adapters
|
|
87
87
|
- Providers: OpenAI plus Anthropic/Gemini/Local sharing the same interface
|
|
88
88
|
- Library-first examples (see below) and tests with fake providers for schemas, parsing, agent wiring
|
|
89
89
|
- PyPI-ready metadata (`pyproject.toml`) using a src-layout package
|
|
@@ -124,8 +124,8 @@ export GEMINI_API_KEY="your-api-key-here" # Optional
|
|
|
124
124
|
## Usage (Library)
|
|
125
125
|
|
|
126
126
|
```python
|
|
127
|
-
from
|
|
128
|
-
from
|
|
127
|
+
from selectools import Agent, AgentConfig, Message, Role, Tool, ToolParameter
|
|
128
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
129
129
|
|
|
130
130
|
# Define a tool
|
|
131
131
|
search_tool = Tool(
|
|
@@ -145,7 +145,7 @@ print(response.content)
|
|
|
145
145
|
|
|
146
146
|
- Define tools (`Tool` or `@tool`/`ToolRegistry`), pick a provider, run `Agent.run([...])`.
|
|
147
147
|
- Add vision by supplying `image_path` on `Message` when the provider supports it.
|
|
148
|
-
- For offline/testing: use the Local provider and/or `
|
|
148
|
+
- For offline/testing: use the Local provider and/or `SELECTOOLS_BBOX_MOCK_JSON=tests/fixtures/bbox_mock.json`.
|
|
149
149
|
- Optional dev helpers (not required for library use): `scripts/smoke_cli.py` for quick provider smokes; `scripts/chat.py` for the vision demo.
|
|
150
150
|
|
|
151
151
|
## Providers (incl. vision & limits)
|
|
@@ -171,8 +171,8 @@ print(response.content)
|
|
|
171
171
|
The simplest possible tool—great for testing your setup:
|
|
172
172
|
|
|
173
173
|
```python
|
|
174
|
-
from
|
|
175
|
-
from
|
|
174
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
175
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
176
176
|
|
|
177
177
|
@tool(description="Echo input back to user")
|
|
178
178
|
def echo(text: str) -> str:
|
|
@@ -188,8 +188,8 @@ print(resp.content)
|
|
|
188
188
|
Build a customer support agent that can search a knowledge base, check order status, and create tickets:
|
|
189
189
|
|
|
190
190
|
```python
|
|
191
|
-
from
|
|
192
|
-
from
|
|
191
|
+
from selectools import Agent, AgentConfig, Message, Role, ToolRegistry
|
|
192
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
193
193
|
import json
|
|
194
194
|
|
|
195
195
|
registry = ToolRegistry()
|
|
@@ -241,9 +241,9 @@ print(response.content)
|
|
|
241
241
|
Detect and annotate objects in images using OpenAI Vision:
|
|
242
242
|
|
|
243
243
|
```python
|
|
244
|
-
from
|
|
245
|
-
from
|
|
246
|
-
from
|
|
244
|
+
from selectools import Agent, AgentConfig, Message, Role
|
|
245
|
+
from selectools.examples.bbox import create_bounding_box_tool
|
|
246
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
247
247
|
|
|
248
248
|
bbox_tool = create_bounding_box_tool()
|
|
249
249
|
agent = Agent(
|
|
@@ -269,8 +269,8 @@ print(response.content)
|
|
|
269
269
|
Chain multiple tools to research a topic, summarize findings, and save results:
|
|
270
270
|
|
|
271
271
|
```python
|
|
272
|
-
from
|
|
273
|
-
from
|
|
272
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
273
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
274
274
|
import json
|
|
275
275
|
|
|
276
276
|
@tool(description="Search academic papers and articles")
|
|
@@ -315,8 +315,8 @@ print(response.content)
|
|
|
315
315
|
Build responsive UIs with streaming responses:
|
|
316
316
|
|
|
317
317
|
```python
|
|
318
|
-
from
|
|
319
|
-
from
|
|
318
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
319
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
320
320
|
import sys
|
|
321
321
|
|
|
322
322
|
@tool(description="Get current time in a timezone")
|
|
@@ -348,9 +348,9 @@ print("\n") # Newline after streaming completes
|
|
|
348
348
|
Keep sensitive credentials out of tool signatures using `injected_kwargs`:
|
|
349
349
|
|
|
350
350
|
```python
|
|
351
|
-
from
|
|
352
|
-
from
|
|
353
|
-
from
|
|
351
|
+
from selectools import Agent, AgentConfig, Message, Role, Tool
|
|
352
|
+
from selectools.tools import ToolParameter
|
|
353
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
354
354
|
import psycopg2
|
|
355
355
|
|
|
356
356
|
def query_database(sql: str, db_connection) -> str:
|
|
@@ -398,8 +398,8 @@ print(response.content)
|
|
|
398
398
|
Develop and test without API calls using the Local provider:
|
|
399
399
|
|
|
400
400
|
```python
|
|
401
|
-
from
|
|
402
|
-
from
|
|
401
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
402
|
+
from selectools.providers.stubs import LocalProvider
|
|
403
403
|
|
|
404
404
|
@tool(description="Format a todo item with priority")
|
|
405
405
|
def create_todo(task: str, priority: str = "medium", due_date: str = None) -> str:
|
|
@@ -425,10 +425,10 @@ print(response.content)
|
|
|
425
425
|
Switch between providers without changing your tool definitions:
|
|
426
426
|
|
|
427
427
|
```python
|
|
428
|
-
from
|
|
429
|
-
from
|
|
430
|
-
from
|
|
431
|
-
from
|
|
428
|
+
from selectools import Agent, AgentConfig, Message, Role, tool
|
|
429
|
+
from selectools.providers.openai_provider import OpenAIProvider
|
|
430
|
+
from selectools.providers.anthropic_provider import AnthropicProvider
|
|
431
|
+
from selectools.providers.gemini_provider import GeminiProvider
|
|
432
432
|
import os
|
|
433
433
|
|
|
434
434
|
@tool(description="Calculate compound interest")
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/selectools/__init__.py
|
|
5
|
+
src/selectools/agent.py
|
|
6
|
+
src/selectools/cli.py
|
|
7
|
+
src/selectools/env.py
|
|
8
|
+
src/selectools/parser.py
|
|
9
|
+
src/selectools/prompt.py
|
|
10
|
+
src/selectools/tools.py
|
|
11
|
+
src/selectools/types.py
|
|
12
|
+
src/selectools.egg-info/PKG-INFO
|
|
13
|
+
src/selectools.egg-info/SOURCES.txt
|
|
14
|
+
src/selectools.egg-info/dependency_links.txt
|
|
15
|
+
src/selectools.egg-info/entry_points.txt
|
|
16
|
+
src/selectools.egg-info/requires.txt
|
|
17
|
+
src/selectools.egg-info/top_level.txt
|
|
18
|
+
src/selectools/examples/bbox.py
|
|
19
|
+
src/selectools/providers/base.py
|
|
20
|
+
src/selectools/providers/openai_provider.py
|
|
21
|
+
src/selectools/providers/stubs.py
|
|
22
|
+
tests/test_framework.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
selectools
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Test Suite for the
|
|
2
|
+
Test Suite for the selectools library.
|
|
3
3
|
|
|
4
4
|
These tests avoid real API calls by using fake providers.
|
|
5
5
|
"""
|
|
@@ -23,12 +23,12 @@ if str(SRC_DIR) not in sys.path:
|
|
|
23
23
|
sys.path.insert(0, str(SRC_DIR))
|
|
24
24
|
|
|
25
25
|
from agent import Agent, AgentConfig, Message, Role, Tool, ToolParameter
|
|
26
|
-
from
|
|
27
|
-
from
|
|
28
|
-
from
|
|
29
|
-
from
|
|
30
|
-
from
|
|
31
|
-
from
|
|
26
|
+
from selectools.tools import ToolRegistry
|
|
27
|
+
from selectools.examples.bbox import BBOX_MOCK_ENV, detect_bounding_box_impl
|
|
28
|
+
from selectools.parser import ToolCallParser
|
|
29
|
+
from selectools.providers.base import ProviderError
|
|
30
|
+
from selectools.providers.stubs import AnthropicProvider, GeminiProvider, LocalProvider
|
|
31
|
+
from selectools.cli import build_parser, run_agent, _default_tools
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class FakeProvider:
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
README.md
|
|
3
|
-
pyproject.toml
|
|
4
|
-
src/selectools.egg-info/PKG-INFO
|
|
5
|
-
src/selectools.egg-info/SOURCES.txt
|
|
6
|
-
src/selectools.egg-info/dependency_links.txt
|
|
7
|
-
src/selectools.egg-info/entry_points.txt
|
|
8
|
-
src/selectools.egg-info/requires.txt
|
|
9
|
-
src/selectools.egg-info/top_level.txt
|
|
10
|
-
src/toolcalling/__init__.py
|
|
11
|
-
src/toolcalling/agent.py
|
|
12
|
-
src/toolcalling/cli.py
|
|
13
|
-
src/toolcalling/env.py
|
|
14
|
-
src/toolcalling/parser.py
|
|
15
|
-
src/toolcalling/prompt.py
|
|
16
|
-
src/toolcalling/tools.py
|
|
17
|
-
src/toolcalling/types.py
|
|
18
|
-
src/toolcalling/examples/bbox.py
|
|
19
|
-
src/toolcalling/providers/base.py
|
|
20
|
-
src/toolcalling/providers/openai_provider.py
|
|
21
|
-
src/toolcalling/providers/stubs.py
|
|
22
|
-
tests/test_framework.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
toolcalling
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{selectools-0.2.0/src/toolcalling → selectools-0.3.0/src/selectools}/providers/openai_provider.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|