fmtr.tools 1.1.1__py3-none-any.whl → 1.4.37__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.
- fmtr/tools/__init__.py +86 -52
- fmtr/tools/ai_tools/__init__.py +2 -2
- fmtr/tools/ai_tools/agentic_tools.py +151 -32
- fmtr/tools/ai_tools/inference_tools.py +2 -1
- fmtr/tools/api_tools.py +73 -12
- fmtr/tools/async_tools.py +4 -0
- fmtr/tools/av_tools.py +7 -0
- fmtr/tools/caching_tools.py +101 -3
- fmtr/tools/constants.py +41 -0
- fmtr/tools/context_tools.py +23 -0
- fmtr/tools/data_modelling_tools.py +227 -14
- fmtr/tools/database_tools/__init__.py +6 -0
- fmtr/tools/database_tools/document.py +51 -0
- fmtr/tools/datatype_tools.py +22 -2
- fmtr/tools/datetime_tools.py +12 -0
- fmtr/tools/debugging_tools.py +60 -1
- fmtr/tools/dns_tools/__init__.py +7 -0
- fmtr/tools/dns_tools/client.py +97 -0
- fmtr/tools/dns_tools/dm.py +257 -0
- fmtr/tools/dns_tools/proxy.py +66 -0
- fmtr/tools/dns_tools/server.py +138 -0
- fmtr/tools/docker_tools/__init__.py +6 -0
- fmtr/tools/entrypoints/__init__.py +0 -0
- fmtr/tools/entrypoints/cache_hfh.py +3 -0
- fmtr/tools/entrypoints/ep_test.py +2 -0
- fmtr/tools/entrypoints/install_yamlscript.py +8 -0
- fmtr/tools/{console_script_tools.py → entrypoints/remote_debug_test.py} +1 -6
- fmtr/tools/entrypoints/shell_debug.py +8 -0
- fmtr/tools/environment_tools.py +3 -2
- fmtr/tools/function_tools.py +77 -1
- fmtr/tools/google_api_tools.py +15 -4
- fmtr/tools/ha_tools/__init__.py +8 -0
- fmtr/tools/ha_tools/constants.py +9 -0
- fmtr/tools/ha_tools/core.py +16 -0
- fmtr/tools/ha_tools/supervisor.py +16 -0
- fmtr/tools/ha_tools/utils.py +46 -0
- fmtr/tools/http_tools.py +52 -0
- fmtr/tools/inherit_tools.py +27 -0
- fmtr/tools/interface_tools/__init__.py +8 -0
- fmtr/tools/interface_tools/context.py +13 -0
- fmtr/tools/interface_tools/controls.py +354 -0
- fmtr/tools/interface_tools/interface_tools.py +189 -0
- fmtr/tools/iterator_tools.py +122 -1
- fmtr/tools/logging_tools.py +99 -18
- fmtr/tools/mqtt_tools.py +89 -0
- fmtr/tools/networking_tools.py +73 -0
- fmtr/tools/packaging_tools.py +14 -0
- fmtr/tools/path_tools/__init__.py +12 -0
- fmtr/tools/path_tools/app_path_tools.py +40 -0
- fmtr/tools/{path_tools.py → path_tools/path_tools.py} +217 -14
- fmtr/tools/path_tools/type_path_tools.py +3 -0
- fmtr/tools/pattern_tools.py +277 -0
- fmtr/tools/pdf_tools.py +39 -1
- fmtr/tools/settings_tools.py +27 -6
- fmtr/tools/setup_tools/__init__.py +8 -0
- fmtr/tools/setup_tools/setup_tools.py +481 -0
- fmtr/tools/string_tools.py +92 -13
- fmtr/tools/tabular_tools.py +61 -0
- fmtr/tools/tools.py +27 -2
- fmtr/tools/version +1 -1
- fmtr/tools/version_tools/__init__.py +12 -0
- fmtr/tools/version_tools/version_tools.py +51 -0
- fmtr/tools/webhook_tools.py +17 -0
- fmtr/tools/yaml_tools.py +64 -5
- fmtr/tools/youtube_tools.py +128 -0
- fmtr_tools-1.4.37.data/scripts/add-service +14 -0
- fmtr_tools-1.4.37.data/scripts/add-user-path +8 -0
- fmtr_tools-1.4.37.data/scripts/apt-headless +23 -0
- fmtr_tools-1.4.37.data/scripts/compose-update +10 -0
- fmtr_tools-1.4.37.data/scripts/docker-sandbox +43 -0
- fmtr_tools-1.4.37.data/scripts/docker-sandbox-init +23 -0
- fmtr_tools-1.4.37.data/scripts/docs-deploy +6 -0
- fmtr_tools-1.4.37.data/scripts/docs-serve +5 -0
- fmtr_tools-1.4.37.data/scripts/download +9 -0
- fmtr_tools-1.4.37.data/scripts/fmtr-test-script +3 -0
- fmtr_tools-1.4.37.data/scripts/ftu +3 -0
- fmtr_tools-1.4.37.data/scripts/ha-addon-launch +16 -0
- fmtr_tools-1.4.37.data/scripts/install-browser +8 -0
- fmtr_tools-1.4.37.data/scripts/parse-args +43 -0
- fmtr_tools-1.4.37.data/scripts/set-password +5 -0
- fmtr_tools-1.4.37.data/scripts/snips-install +14 -0
- fmtr_tools-1.4.37.data/scripts/ssh-auth +28 -0
- fmtr_tools-1.4.37.data/scripts/ssh-serve +15 -0
- fmtr_tools-1.4.37.data/scripts/vlc-tn +10 -0
- fmtr_tools-1.4.37.data/scripts/vm-launch +17 -0
- {fmtr_tools-1.1.1.dist-info → fmtr_tools-1.4.37.dist-info}/METADATA +178 -54
- fmtr_tools-1.4.37.dist-info/RECORD +122 -0
- {fmtr_tools-1.1.1.dist-info → fmtr_tools-1.4.37.dist-info}/WHEEL +1 -1
- fmtr_tools-1.4.37.dist-info/entry_points.txt +6 -0
- fmtr_tools-1.4.37.dist-info/top_level.txt +1 -0
- fmtr/tools/docker_tools.py +0 -30
- fmtr/tools/interface_tools.py +0 -64
- fmtr/tools/version_tools.py +0 -62
- fmtr_tools-1.1.1.dist-info/RECORD +0 -65
- fmtr_tools-1.1.1.dist-info/entry_points.txt +0 -3
- fmtr_tools-1.1.1.dist-info/top_level.txt +0 -2
- {fmtr_tools-1.1.1.dist-info → fmtr_tools-1.4.37.dist-info}/licenses/LICENSE +0 -0
fmtr/tools/__init__.py
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
__version__ = version.read()
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import fmtr.tools.async_tools as aio
|
|
2
|
+
import fmtr.tools.database_tools as db
|
|
6
3
|
import fmtr.tools.dataclass_tools as dataclass
|
|
7
4
|
import fmtr.tools.datatype_tools as datatype
|
|
8
5
|
import fmtr.tools.environment_tools as env
|
|
@@ -10,156 +7,193 @@ import fmtr.tools.environment_tools as environment
|
|
|
10
7
|
import fmtr.tools.function_tools as function
|
|
11
8
|
import fmtr.tools.hash_tools as hash
|
|
12
9
|
import fmtr.tools.import_tools as import_
|
|
10
|
+
import fmtr.tools.inherit_tools as inherit
|
|
13
11
|
import fmtr.tools.iterator_tools as iterator
|
|
14
12
|
import fmtr.tools.json_tools as json
|
|
13
|
+
import fmtr.tools.logging_tools as logging
|
|
14
|
+
import fmtr.tools.name_tools as name
|
|
15
|
+
import fmtr.tools.networking_tools as net
|
|
16
|
+
import fmtr.tools.packaging_tools as packaging
|
|
15
17
|
import fmtr.tools.path_tools as path
|
|
16
18
|
import fmtr.tools.platform_tools as platform
|
|
17
19
|
import fmtr.tools.random_tools as random
|
|
20
|
+
import fmtr.tools.setup_tools as setup
|
|
18
21
|
import fmtr.tools.string_tools as string
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
from fmtr.tools
|
|
23
|
-
|
|
24
|
-
from fmtr.tools
|
|
25
|
-
from fmtr.tools
|
|
22
|
+
from fmtr.tools import ai_tools as ai
|
|
23
|
+
from fmtr.tools import datetime_tools as dt
|
|
24
|
+
from fmtr.tools import dns_tools as dns
|
|
25
|
+
from fmtr.tools import docker_tools as docker
|
|
26
|
+
from fmtr.tools import ha_tools as ha
|
|
27
|
+
from fmtr.tools import interface_tools as interface
|
|
28
|
+
from fmtr.tools import version_tools as version
|
|
26
29
|
from fmtr.tools.constants import Constants
|
|
30
|
+
from fmtr.tools.import_tools import MissingExtraMockModule
|
|
31
|
+
from fmtr.tools.logging_tools import logger
|
|
32
|
+
# Submodules
|
|
33
|
+
from fmtr.tools.path_tools import Path, PackagePaths, AppPaths
|
|
34
|
+
from fmtr.tools.setup_tools import Setup, SetupPaths, Dependencies, Tools
|
|
27
35
|
|
|
28
36
|
try:
|
|
29
37
|
from fmtr.tools import augmentation_tools as augmentation
|
|
30
|
-
except
|
|
38
|
+
except ModuleNotFoundError as exception:
|
|
31
39
|
augmentation = MissingExtraMockModule('augmentation', exception)
|
|
32
40
|
|
|
33
41
|
try:
|
|
34
42
|
from fmtr.tools import yaml_tools as yaml
|
|
35
|
-
except
|
|
43
|
+
except ModuleNotFoundError as exception:
|
|
36
44
|
yaml = MissingExtraMockModule('yaml', exception)
|
|
37
45
|
|
|
38
|
-
try:
|
|
39
|
-
from fmtr.tools import docker_tools as docker
|
|
40
|
-
from fmtr.tools.docker_tools import Container
|
|
41
|
-
except ImportError as exception:
|
|
42
|
-
docker = Container = MissingExtraMockModule('docker.api', exception)
|
|
43
46
|
|
|
44
47
|
try:
|
|
45
48
|
from fmtr.tools import parallel_tools as parallel
|
|
46
|
-
except
|
|
49
|
+
except ModuleNotFoundError as exception:
|
|
47
50
|
parallel = MissingExtraMockModule('parallel', exception)
|
|
48
51
|
|
|
49
52
|
try:
|
|
50
53
|
from fmtr.tools import profiling_tools as profiling
|
|
51
54
|
from fmtr.tools.profiling_tools import Timer
|
|
52
|
-
except
|
|
55
|
+
except ModuleNotFoundError as exception:
|
|
53
56
|
profiling = Timer = MissingExtraMockModule('profiling', exception)
|
|
54
57
|
|
|
55
58
|
try:
|
|
56
59
|
import fmtr.tools.process_tools as process
|
|
57
60
|
from fmtr.tools.process_tools import ContextProcess
|
|
58
|
-
except
|
|
61
|
+
except ModuleNotFoundError as exception:
|
|
59
62
|
process = ContextProcess = MissingExtraMockModule('process', exception)
|
|
60
63
|
|
|
61
64
|
try:
|
|
62
65
|
from fmtr.tools import tokenization_tools as tokenization
|
|
63
|
-
except
|
|
66
|
+
except ModuleNotFoundError as exception:
|
|
64
67
|
tokenization = MissingExtraMockModule('tokenization', exception)
|
|
65
68
|
|
|
66
69
|
try:
|
|
67
70
|
from fmtr.tools import unicode_tools as unicode
|
|
68
|
-
except
|
|
71
|
+
except ModuleNotFoundError as exception:
|
|
69
72
|
unicode = MissingExtraMockModule('unicode', exception)
|
|
70
73
|
|
|
71
74
|
try:
|
|
72
75
|
from fmtr.tools import netrc_tools as netrc
|
|
73
|
-
except
|
|
76
|
+
except ModuleNotFoundError as exception:
|
|
74
77
|
netrc = MissingExtraMockModule('netrc', exception)
|
|
75
78
|
|
|
76
79
|
try:
|
|
77
80
|
from fmtr.tools import spaces_tools as spaces
|
|
78
|
-
except
|
|
81
|
+
except ModuleNotFoundError as exception:
|
|
79
82
|
spaces = MissingExtraMockModule('spaces', exception)
|
|
80
83
|
|
|
81
84
|
try:
|
|
82
85
|
from fmtr.tools import hfh_tools as hfh
|
|
83
|
-
except
|
|
86
|
+
except ModuleNotFoundError as exception:
|
|
84
87
|
hfh = MissingExtraMockModule('hfh', exception)
|
|
85
88
|
|
|
86
89
|
try:
|
|
87
90
|
from fmtr.tools import merging_tools as merging
|
|
88
91
|
from fmtr.tools.merging_tools import merge
|
|
89
|
-
except
|
|
92
|
+
except ModuleNotFoundError as exception:
|
|
90
93
|
merging = merge = MissingExtraMockModule('merging', exception)
|
|
91
94
|
|
|
92
95
|
try:
|
|
93
96
|
from fmtr.tools import api_tools as api
|
|
94
|
-
except
|
|
97
|
+
except ModuleNotFoundError as exception:
|
|
95
98
|
api = MissingExtraMockModule('api', exception)
|
|
96
99
|
|
|
97
|
-
try:
|
|
98
|
-
from fmtr.tools import ai_tools as ai
|
|
99
|
-
except ImportError as exception:
|
|
100
|
-
ai = MissingExtraMockModule('ai', exception)
|
|
101
|
-
|
|
102
100
|
try:
|
|
103
101
|
from fmtr.tools import data_modelling_tools as dm
|
|
104
|
-
except
|
|
102
|
+
except ModuleNotFoundError as exception:
|
|
105
103
|
dm = MissingExtraMockModule('dm', exception)
|
|
106
104
|
|
|
107
105
|
try:
|
|
108
106
|
from fmtr.tools import json_fix_tools as json_fix
|
|
109
|
-
except
|
|
107
|
+
except ModuleNotFoundError as exception:
|
|
110
108
|
json_fix = MissingExtraMockModule('json_fix', exception)
|
|
111
109
|
|
|
112
110
|
try:
|
|
113
111
|
from fmtr.tools import semantic_tools as semantic
|
|
114
|
-
except
|
|
112
|
+
except ModuleNotFoundError as exception:
|
|
115
113
|
semantic = MissingExtraMockModule('semantic', exception)
|
|
116
114
|
|
|
117
115
|
try:
|
|
118
116
|
from fmtr.tools import metric_tools as metric
|
|
119
|
-
except
|
|
117
|
+
except ModuleNotFoundError as exception:
|
|
120
118
|
metric = MissingExtraMockModule('metric', exception)
|
|
121
119
|
|
|
122
120
|
try:
|
|
123
121
|
from fmtr.tools import html_tools as html
|
|
124
|
-
except
|
|
122
|
+
except ModuleNotFoundError as exception:
|
|
125
123
|
html = MissingExtraMockModule('html', exception)
|
|
126
124
|
|
|
127
|
-
try:
|
|
128
|
-
from fmtr.tools import interface_tools as interface
|
|
129
|
-
except ImportError as exception:
|
|
130
|
-
interface = MissingExtraMockModule('interface', exception)
|
|
131
|
-
|
|
132
125
|
try:
|
|
133
126
|
from fmtr.tools import openai_tools as openai
|
|
134
|
-
except
|
|
127
|
+
except ModuleNotFoundError as exception:
|
|
135
128
|
openai = MissingExtraMockModule('openai', exception)
|
|
136
129
|
|
|
137
130
|
try:
|
|
138
131
|
from fmtr.tools import google_api_tools as google_api
|
|
139
|
-
except
|
|
132
|
+
except ModuleNotFoundError as exception:
|
|
140
133
|
google_api = MissingExtraMockModule('google.api', exception)
|
|
141
134
|
|
|
142
135
|
try:
|
|
143
136
|
from fmtr.tools import caching_tools as caching
|
|
144
|
-
except
|
|
137
|
+
except ModuleNotFoundError as exception:
|
|
145
138
|
caching = MissingExtraMockModule('caching', exception)
|
|
146
139
|
|
|
147
140
|
try:
|
|
148
141
|
from fmtr.tools import pdf_tools as pdf
|
|
149
|
-
except
|
|
142
|
+
except ModuleNotFoundError as exception:
|
|
150
143
|
pdf = MissingExtraMockModule('pdf', exception)
|
|
151
144
|
|
|
152
145
|
try:
|
|
153
146
|
from fmtr.tools import tabular_tools as tabular
|
|
154
|
-
except
|
|
147
|
+
except ModuleNotFoundError as exception:
|
|
155
148
|
tabular = MissingExtraMockModule('tabular', exception)
|
|
156
149
|
|
|
157
150
|
try:
|
|
158
151
|
from fmtr.tools import debugging_tools as debug
|
|
159
|
-
except
|
|
152
|
+
except ModuleNotFoundError as exception:
|
|
160
153
|
debug = MissingExtraMockModule('debug', exception)
|
|
161
154
|
|
|
162
155
|
try:
|
|
163
156
|
from fmtr.tools import settings_tools as sets
|
|
164
|
-
except
|
|
165
|
-
sets = MissingExtraMockModule('sets', exception)
|
|
157
|
+
except ModuleNotFoundError as exception:
|
|
158
|
+
sets = MissingExtraMockModule('sets', exception)
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
from fmtr.tools import pattern_tools as patterns
|
|
162
|
+
except ModuleNotFoundError as exception:
|
|
163
|
+
patterns = MissingExtraMockModule('patterns', exception)
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
from fmtr.tools import http_tools as http
|
|
167
|
+
from fmtr.tools.http_tools import Client
|
|
168
|
+
except ModuleNotFoundError as exception:
|
|
169
|
+
http = Client = MissingExtraMockModule('http', exception)
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
from fmtr.tools import webhook_tools as webhook
|
|
173
|
+
except ModuleNotFoundError as exception:
|
|
174
|
+
webhook = MissingExtraMockModule('webhook', exception)
|
|
175
|
+
|
|
176
|
+
try:
|
|
177
|
+
from fmtr.tools import mqtt_tools as mqtt
|
|
178
|
+
except ModuleNotFoundError as exception:
|
|
179
|
+
mqtt = MissingExtraMockModule('mqtt', exception)
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
from fmtr.tools import av_tools as av
|
|
183
|
+
except ModuleNotFoundError as exception:
|
|
184
|
+
av = MissingExtraMockModule('av', exception)
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
from fmtr.tools import youtube_tools as youtube
|
|
188
|
+
except ModuleNotFoundError as exception:
|
|
189
|
+
youtube = MissingExtraMockModule('youtube', exception)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def get_version():
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
Defer reading version
|
|
197
|
+
|
|
198
|
+
"""
|
|
199
|
+
return version.read()
|
fmtr/tools/ai_tools/__init__.py
CHANGED
|
@@ -2,10 +2,10 @@ from fmtr.tools.import_tools import MissingExtraMockModule
|
|
|
2
2
|
|
|
3
3
|
try:
|
|
4
4
|
from fmtr.tools.ai_tools import inference_tools as infer
|
|
5
|
-
except
|
|
5
|
+
except ModuleNotFoundError as exception:
|
|
6
6
|
infer = MissingExtraMockModule('ai', exception)
|
|
7
7
|
|
|
8
8
|
try:
|
|
9
9
|
from fmtr.tools.ai_tools import agentic_tools as agentic
|
|
10
|
-
except
|
|
10
|
+
except ModuleNotFoundError as exception:
|
|
11
11
|
agentic = MissingExtraMockModule('ai.client', exception)
|
|
@@ -1,33 +1,57 @@
|
|
|
1
|
+
from typing import List, Optional, Any, Annotated, Generic
|
|
2
|
+
|
|
1
3
|
import pydantic_ai
|
|
2
|
-
from
|
|
4
|
+
from pydantic import PlainValidator
|
|
5
|
+
from pydantic_ai import RunContext, ModelRetry
|
|
6
|
+
from pydantic_ai._output import OutputDataT
|
|
3
7
|
from pydantic_ai.agent import AgentRunResult, Agent
|
|
4
|
-
from pydantic_ai.messages import ModelRequest, RetryPromptPart
|
|
5
8
|
from pydantic_ai.models.openai import OpenAIModel
|
|
9
|
+
from pydantic_ai.output import OutputSpec, NativeOutput, ToolOutput
|
|
6
10
|
from pydantic_ai.providers.openai import OpenAIProvider
|
|
11
|
+
from pydantic_ai.tools import AgentDepsT
|
|
7
12
|
|
|
8
13
|
from fmtr.tools import environment_tools as env
|
|
9
14
|
from fmtr.tools.constants import Constants
|
|
15
|
+
from fmtr.tools.logging_tools import logger
|
|
16
|
+
from fmtr.tools.string_tools import truncate_mid
|
|
10
17
|
|
|
11
18
|
pydantic_ai.Agent.instrument_all()
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
|
|
21
|
+
class Validator:
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
Subclassable validator
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
async def validate(self, ctx: RunContext[Any], output: Any) -> List[str]:
|
|
29
|
+
raise NotImplementedError()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
api_key = env.get(Constants.FMTR_OPENAI_API_KEY_KEY, None)
|
|
33
|
+
|
|
34
|
+
class Task(Generic[AgentDepsT, OutputDataT]):
|
|
14
35
|
"""
|
|
15
36
|
|
|
16
37
|
Linear task definition, as Agent configuration and typing, plus state history.
|
|
17
38
|
|
|
18
39
|
"""
|
|
19
40
|
|
|
20
|
-
|
|
41
|
+
TypeDeps = str
|
|
42
|
+
TypeOutput = str
|
|
43
|
+
|
|
44
|
+
PROVIDER = OpenAIProvider(api_key=api_key) if api_key else None
|
|
21
45
|
|
|
22
46
|
API_HOST_FMTR = env.get(Constants.FMTR_AI_HOST_KEY, Constants.FMTR_AI_HOST_DEFAULT)
|
|
23
47
|
API_URL_FMTR = f'https://{API_HOST_FMTR}/v1'
|
|
24
48
|
PROVIDER_FMTR = OpenAIProvider(base_url=API_URL_FMTR)
|
|
25
49
|
|
|
26
50
|
MODEL_ID = 'gpt-4o'
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
RESULT_TYPE = str
|
|
51
|
+
MODEL_ID_FMTR = 'qwen2.5-coder:32b'
|
|
52
|
+
SYSTEM_PROMPT_STATIC = None
|
|
30
53
|
RESULT_RETRIES = 5
|
|
54
|
+
VALIDATORS: List[Validator] = []
|
|
31
55
|
|
|
32
56
|
def __init__(self, *args, **kwargs):
|
|
33
57
|
"""
|
|
@@ -37,64 +61,159 @@ class Task:
|
|
|
37
61
|
"""
|
|
38
62
|
|
|
39
63
|
self.model = OpenAIModel(self.MODEL_ID, provider=self.PROVIDER)
|
|
40
|
-
self.agent = Agent(
|
|
64
|
+
self.agent = Agent[AgentDepsT, OutputDataT](
|
|
41
65
|
*args,
|
|
42
66
|
model=self.model,
|
|
43
|
-
system_prompt=self.
|
|
44
|
-
deps_type=self.
|
|
45
|
-
|
|
46
|
-
|
|
67
|
+
system_prompt=self.SYSTEM_PROMPT_STATIC or [],
|
|
68
|
+
deps_type=self.TypeDeps,
|
|
69
|
+
output_type=self.tool_output,
|
|
70
|
+
output_retries=self.RESULT_RETRIES,
|
|
47
71
|
**kwargs
|
|
48
72
|
)
|
|
49
73
|
|
|
50
74
|
self.agent.output_validator(self.validate)
|
|
75
|
+
self.agent.system_prompt(self.add_system_prompt)
|
|
51
76
|
self.history = []
|
|
52
77
|
|
|
53
|
-
|
|
78
|
+
@property
|
|
79
|
+
def tool_output(self) -> OutputSpec[OutputDataT]:
|
|
54
80
|
"""
|
|
55
81
|
|
|
56
|
-
|
|
82
|
+
Tool output specification (e.g. ToolOutput/NativeOutput etc.)
|
|
57
83
|
|
|
58
84
|
"""
|
|
85
|
+
return ToolOutput(self.TypeOutput)
|
|
59
86
|
|
|
60
|
-
result = await self.agent.run(*args, message_history=self.history, **kwargs)
|
|
61
|
-
self.history = result.all_messages()
|
|
62
|
-
return result
|
|
63
87
|
|
|
64
|
-
|
|
88
|
+
@property
|
|
89
|
+
def sync_runner(self):
|
|
65
90
|
"""
|
|
66
91
|
|
|
67
|
-
|
|
92
|
+
Convenience/debug function to run without async.
|
|
68
93
|
|
|
69
94
|
"""
|
|
70
|
-
|
|
71
|
-
|
|
95
|
+
import asyncio
|
|
96
|
+
return asyncio.run
|
|
72
97
|
|
|
73
|
-
|
|
74
|
-
|
|
98
|
+
async def run(self, *args, deps=None, **kwargs) -> AgentRunResult[OutputDataT]:
|
|
99
|
+
"""
|
|
75
100
|
|
|
76
|
-
|
|
101
|
+
Run Agent with deps-relative user prompt and while storing history
|
|
77
102
|
|
|
78
|
-
|
|
103
|
+
"""
|
|
104
|
+
result = await self.agent.run(*args, user_prompt=self.get_prompt(deps), deps=deps, message_history=self.history, **kwargs)
|
|
105
|
+
self.history = result.all_messages()
|
|
79
106
|
return result
|
|
80
107
|
|
|
81
|
-
async def validate(self, ctx: RunContext[
|
|
108
|
+
async def validate(self, ctx: RunContext[AgentDepsT], output: OutputDataT) -> OutputDataT:
|
|
82
109
|
"""
|
|
83
110
|
|
|
84
|
-
|
|
111
|
+
Aggregate any validation failures and combine them into a single ModelRetry exception
|
|
85
112
|
|
|
86
113
|
"""
|
|
114
|
+
msgs = []
|
|
115
|
+
for validator in self.VALIDATORS:
|
|
116
|
+
msgs += validator.validate(ctx, output)
|
|
117
|
+
|
|
118
|
+
if msgs:
|
|
119
|
+
msg = '. '.join(msgs)
|
|
120
|
+
logger.warning(msg)
|
|
121
|
+
raise ModelRetry(msg)
|
|
122
|
+
|
|
87
123
|
return output
|
|
88
124
|
|
|
125
|
+
def get_prompt(self, deps: Optional[AgentDepsT]) -> Optional[str]:
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
Dummy prompt generator
|
|
89
129
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
130
|
+
"""
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
def add_system_prompt(self, ctx: RunContext[AgentDepsT]) -> str | List[str]:
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
Dummy system prompt append
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
return []
|
|
141
|
+
|
|
142
|
+
def reset(self):
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
Reset the task by deleting its history.
|
|
146
|
+
|
|
147
|
+
"""
|
|
148
|
+
self.history = []
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def tool_schema(self):
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
Impossible to find otherwise.
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
return self.agent._output_toolset
|
|
158
|
+
|
|
159
|
+
def __repr__(self):
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
String representation of the object
|
|
163
|
+
|
|
164
|
+
"""
|
|
165
|
+
return f'{self.__class__.__name__}({repr(truncate_mid(self.SYSTEM_PROMPT_STATIC, 100))})'
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def default_prompt_none_specified(text):
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
If the prompt is falsey, explicitly state None Specified
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
if not (text or '').strip():
|
|
175
|
+
return Constants.PROMPT_NONE_SPECIFIED
|
|
176
|
+
return text
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
StringDefaultNoneSpecified = Annotated[Optional[str], PlainValidator(default_prompt_none_specified)]
|
|
93
180
|
|
|
94
181
|
|
|
95
182
|
if __name__ == '__main__':
|
|
96
183
|
import asyncio
|
|
184
|
+
from fmtr.tools import dm
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class TestOutput(dm.Base):
|
|
188
|
+
text: str
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class TestDeps(dm.Base):
|
|
192
|
+
lang: str
|
|
193
|
+
subject: str
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class TaskTest(Task):
|
|
197
|
+
PROVIDER = Task.PROVIDER_FMTR
|
|
198
|
+
MODEL_ID = Task.MODEL_ID_FMTR
|
|
199
|
+
TypeOutput = TestOutput
|
|
200
|
+
SYSTEM_PROMPT_STATIC = 'Tell the user jokes.'
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def tool_output(self) -> OutputSpec[TestOutput]:
|
|
204
|
+
return NativeOutput(self.TypeOutput)
|
|
205
|
+
|
|
206
|
+
def add_system_prompt(self, ctx: RunContext[TestDeps]) -> str:
|
|
207
|
+
return f'The jokes must be in the {ctx.deps.lang} language.'
|
|
208
|
+
|
|
209
|
+
def get_prompt(self, deps: Optional[TestDeps]) -> str:
|
|
210
|
+
return f'Tell me one about {deps.subject}.'
|
|
97
211
|
|
|
98
212
|
task = TaskTest()
|
|
99
|
-
|
|
100
|
-
|
|
213
|
+
deps = TestDeps(lang='English', subject='eggs')
|
|
214
|
+
result1 = task.sync_runner(task.run(deps=deps))
|
|
215
|
+
result1
|
|
216
|
+
|
|
217
|
+
deps = TestDeps(lang='German', subject='sausages')
|
|
218
|
+
result2 = task.sync_runner(task.run(deps=deps))
|
|
219
|
+
result2
|
|
@@ -266,6 +266,7 @@ class BulkInferenceManager:
|
|
|
266
266
|
yield ids_output
|
|
267
267
|
|
|
268
268
|
except RuntimeError as exception:
|
|
269
|
+
# Instability causes CUBLAS_STATUS in str(exception) too
|
|
269
270
|
if "CUDA out of memory" in str(exception):
|
|
270
271
|
logger.warning(f"Ran out of memory. Reducing batch size: {repr(exception)}")
|
|
271
272
|
batcher.reduce()
|
|
@@ -412,5 +413,5 @@ def tst_tool():
|
|
|
412
413
|
|
|
413
414
|
|
|
414
415
|
if __name__ == '__main__':
|
|
415
|
-
texts =
|
|
416
|
+
texts = tst()
|
|
416
417
|
texts
|
fmtr/tools/api_tools.py
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import logging
|
|
2
2
|
from dataclasses import dataclass
|
|
3
|
-
from fastapi import FastAPI, Request
|
|
4
3
|
from typing import Callable, List, Optional, Union
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
import uvicorn
|
|
6
|
+
from fastapi import FastAPI, Request
|
|
7
|
+
|
|
8
|
+
from fmtr.tools import environment_tools
|
|
7
9
|
from fmtr.tools.iterator_tools import enlist
|
|
8
10
|
from fmtr.tools.logging_tools import logger
|
|
9
11
|
|
|
12
|
+
for name in ["uvicorn.access", "uvicorn.error", "uvicorn"]:
|
|
13
|
+
logger_uvicorn = logging.getLogger(name)
|
|
14
|
+
logger_uvicorn.handlers.clear()
|
|
15
|
+
logger_uvicorn.propagate = False
|
|
10
16
|
|
|
11
17
|
@dataclass
|
|
12
18
|
class Endpoint:
|
|
@@ -24,7 +30,7 @@ class Endpoint:
|
|
|
24
30
|
self.tags = enlist(self.tags)
|
|
25
31
|
|
|
26
32
|
|
|
27
|
-
class
|
|
33
|
+
class Base:
|
|
28
34
|
"""
|
|
29
35
|
|
|
30
36
|
Simple API base class, generalising endpoint-as-method config.
|
|
@@ -33,6 +39,9 @@ class ApiBase:
|
|
|
33
39
|
TITLE = 'Base API'
|
|
34
40
|
HOST = '0.0.0.0'
|
|
35
41
|
PORT = 8080
|
|
42
|
+
SWAGGER_PARAMS = dict(tryItOutEnabled=True)
|
|
43
|
+
URL = None
|
|
44
|
+
URL_DOCS = '/docs'
|
|
36
45
|
|
|
37
46
|
def add_endpoint(self, endpoint: Endpoint):
|
|
38
47
|
"""
|
|
@@ -51,12 +60,13 @@ class ApiBase:
|
|
|
51
60
|
)(endpoint.method)
|
|
52
61
|
|
|
53
62
|
def __init__(self):
|
|
54
|
-
self.app = FastAPI(title=self.TITLE)
|
|
63
|
+
self.app = FastAPI(title=self.TITLE, swagger_ui_parameters=self.SWAGGER_PARAMS, docs_url=self.URL_DOCS)
|
|
64
|
+
logger.instrument_fastapi(self.app)
|
|
55
65
|
|
|
56
66
|
for endpoint in self.get_endpoints():
|
|
57
67
|
self.add_endpoint(endpoint)
|
|
58
68
|
|
|
59
|
-
if
|
|
69
|
+
if environment_tools.IS_DEV:
|
|
60
70
|
self.app.exception_handler(Exception)(self.handle_exception)
|
|
61
71
|
|
|
62
72
|
def get_endpoints(self) -> List[Endpoint]:
|
|
@@ -80,18 +90,69 @@ class ApiBase:
|
|
|
80
90
|
exception
|
|
81
91
|
raise
|
|
82
92
|
|
|
93
|
+
@property
|
|
94
|
+
def url(self) -> str:
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
Default URL unless overridden.
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
if self.URL:
|
|
101
|
+
url = self.URL
|
|
102
|
+
else:
|
|
103
|
+
url = f'http://{self.HOST}:{self.PORT}'
|
|
104
|
+
return url
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def message(self) -> str:
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
Launch message.
|
|
111
|
+
|
|
112
|
+
"""
|
|
113
|
+
return f"Launching {self.TITLE} at {self.url}"
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def config(self) -> uvicorn.Config:
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
Uvicorn config.
|
|
120
|
+
|
|
121
|
+
"""
|
|
122
|
+
return uvicorn.Config(self.app, host=self.HOST, port=self.PORT, access_log=False)
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def server(self) -> uvicorn.Server:
|
|
126
|
+
""""
|
|
127
|
+
|
|
128
|
+
Uvicorn server.
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
return uvicorn.Server(self.config)
|
|
83
132
|
|
|
84
133
|
@classmethod
|
|
85
|
-
def
|
|
134
|
+
async def launch_async(cls, *args, **kwargs):
|
|
86
135
|
"""
|
|
87
136
|
|
|
88
|
-
Initialise
|
|
137
|
+
Initialise and launch.
|
|
89
138
|
|
|
90
139
|
"""
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
140
|
+
|
|
141
|
+
self = cls(*args, **kwargs)
|
|
142
|
+
logger.info(self.message)
|
|
143
|
+
await self.server.serve()
|
|
144
|
+
|
|
145
|
+
@classmethod
|
|
146
|
+
def launch(cls, *args, **kwargs):
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
Convenience method to launch async from a regular context.
|
|
150
|
+
|
|
151
|
+
"""
|
|
152
|
+
import asyncio
|
|
153
|
+
return asyncio.run(cls.launch_async(*args, **kwargs))
|
|
154
|
+
|
|
94
155
|
|
|
95
156
|
|
|
96
157
|
if __name__ == '__main__':
|
|
97
|
-
|
|
158
|
+
Base.launch()
|
fmtr/tools/async_tools.py
CHANGED