fmtr.tools 1.1.3__py3-none-any.whl → 1.1.5__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 fmtr.tools might be problematic. Click here for more details.

@@ -1,9 +1,9 @@
1
1
  import pydantic_ai
2
2
  from pydantic_ai import RunContext
3
3
  from pydantic_ai.agent import AgentRunResult, Agent
4
- from pydantic_ai.messages import ModelRequest, RetryPromptPart
5
4
  from pydantic_ai.models.openai import OpenAIModel
6
5
  from pydantic_ai.providers.openai import OpenAIProvider
6
+ from typing import List, Optional
7
7
 
8
8
  from fmtr.tools import environment_tools as env
9
9
  from fmtr.tools.constants import Constants
@@ -25,7 +25,7 @@ class Task:
25
25
 
26
26
  MODEL_ID = 'gpt-4o'
27
27
  MODEL_ID_FMTR = 'qwen2.5-coder:14b'
28
- SYSTEM_PROMPT = None
28
+ SYSTEM_PROMPT_STATIC = None
29
29
  DEPS_TYPE = str
30
30
  RESULT_TYPE = str
31
31
  RESULT_RETRIES = 5
@@ -41,7 +41,7 @@ class Task:
41
41
  self.agent = Agent(
42
42
  *args,
43
43
  model=self.model,
44
- system_prompt=self.SYSTEM_PROMPT or [],
44
+ system_prompt=self.SYSTEM_PROMPT_STATIC or [],
45
45
  deps_type=self.DEPS_TYPE,
46
46
  result_type=self.RESULT_TYPE,
47
47
  result_retries=self.RESULT_RETRIES,
@@ -49,58 +49,85 @@ class Task:
49
49
  )
50
50
 
51
51
  self.agent.output_validator(self.validate)
52
+ self.agent.system_prompt(self.add_system_prompt)
52
53
  self.history = []
53
54
 
54
- async def run(self, *args, **kwargs) -> AgentRunResult[RESULT_TYPE]:
55
+ @property
56
+ def sync_runner(self):
55
57
  """
56
58
 
57
- Run Agent storing history
59
+ Convenience/debug function to run without async.
58
60
 
59
61
  """
62
+ import asyncio
63
+ return asyncio.run
60
64
 
61
- result = await self.agent.run(*args, message_history=self.history, **kwargs)
65
+ async def run(self, *args, deps=None, **kwargs) -> AgentRunResult[RESULT_TYPE]:
66
+ """
67
+
68
+ Run Agent with deps-relative user prompt and while storing history
69
+
70
+ """
71
+ result = await self.agent.run(*args, user_prompt=self.get_prompt(deps), deps=deps, message_history=self.history, **kwargs)
62
72
  self.history = result.all_messages()
63
73
  return result
64
74
 
65
- async def revert(self, msg, deps):
75
+ async def validate(self, ctx: RunContext[DEPS_TYPE], output: RESULT_TYPE) -> RESULT_TYPE:
66
76
  """
67
77
 
68
- Post-hoc, user-initiated tool retry.
78
+ Dummy validator
69
79
 
70
80
  """
71
- msg_final = self.history.pop(-1)
72
- tool_return_part = msg_final.parts[0]
81
+ return output
73
82
 
74
- retry_prompt = RetryPromptPart(content=msg, tool_name=tool_return_part.tool_name, tool_call_id=tool_return_part.tool_call_id, timestamp=tool_return_part.timestamp, part_kind='retry-prompt')
75
- retry_request = ModelRequest(parts=[retry_prompt], instructions=msg_final.instructions, kind='request')
83
+ def get_prompt(self, deps: Optional[DEPS_TYPE]) -> Optional[str]:
84
+ """
76
85
 
77
- self.history.append(retry_request)
86
+ Dummy prompt generator
78
87
 
79
- result = await Task.run(self, deps=deps)
80
- return result
88
+ """
89
+ return None
81
90
 
82
- async def validate(self, ctx: RunContext[DEPS_TYPE], output: RESULT_TYPE) -> RESULT_TYPE:
91
+ def add_system_prompt(self, ctx: RunContext[DEPS_TYPE]) -> str | List[str]:
83
92
  """
84
93
 
85
- Dummy validator
94
+ Dummy system prompt append
86
95
 
87
96
  """
88
- return output
97
+
98
+ return []
89
99
 
90
100
  if __name__ == '__main__':
91
101
  import asyncio
92
102
  from fmtr.tools import dm
93
103
 
94
104
 
95
- class TestOutput(dm.BaseModel):
105
+ class TestOutput(dm.Base):
96
106
  text: str
97
107
 
98
108
 
109
+ class TestDeps(dm.Base):
110
+ lang: str
111
+ subject: str
112
+
113
+
99
114
  class TaskTest(Task):
100
- PROVIDER = Task.PROVIDER_FMTR
101
- MODEL_ID = 'qwen2.5-coder:14b'
115
+ # PROVIDER = Task.PROVIDER_FMTR
116
+ # MODEL_ID = 'qwen2.5-coder:14b'
102
117
  RESULT_TYPE = TestOutput
118
+ SYSTEM_PROMPT_STATIC = 'Tell the user jokes.'
119
+
120
+ def add_system_prompt(self, ctx: RunContext[TestDeps]) -> str:
121
+ return f'The jokes must be in the {ctx.deps.lang} language.'
122
+
123
+ def get_prompt(self, deps: Optional[TestDeps]) -> str:
124
+ return f'Tell me one about {deps.subject}.'
103
125
 
104
126
  task = TaskTest()
105
- result = asyncio.run(task.run('Hello! What is your name?'))
106
- result
127
+ deps = TestDeps(lang='English', subject='eggs')
128
+ result1 = task.sync_runner(task.run(deps=deps))
129
+ result1
130
+
131
+ deps = TestDeps(lang='German', subject='sausages')
132
+ result2 = task.sync_runner(task.run(deps=deps))
133
+ result2
fmtr/tools/constants.py CHANGED
@@ -31,3 +31,4 @@ class Constants:
31
31
  FILENAME_CONFIG = 'settings.yaml'
32
32
  DIR_NAME_ARTIFACTS = 'artifacts'
33
33
  FILENAME_VERSION = 'version'
34
+ DIR_NAME_HF = 'hf'
fmtr/tools/path_tools.py CHANGED
@@ -228,7 +228,14 @@ class PackagePaths:
228
228
  Path of artifacts directory.
229
229
 
230
230
  """
231
- return self.repo / self.dir_name_artifacts
231
+
232
+ from fmtr.tools import env
233
+ if env.IS_DEBUG:
234
+ path = self.repo / self.dir_name_artifacts
235
+ else:
236
+ path = Path('/') / self.dir_name_artifacts
237
+
238
+ return path
232
239
 
233
240
  @property
234
241
  def settings(self) -> Path:
@@ -239,6 +246,15 @@ class PackagePaths:
239
246
  """
240
247
  return self.artifacts / self.filename_config
241
248
 
249
+ @property
250
+ def hf(self) -> Path:
251
+ """
252
+
253
+ Path of HuggingFace directory
254
+
255
+ """
256
+ return self.artifacts / Constants.DIR_NAME_HF
257
+
242
258
  def __repr__(self) -> str:
243
259
  """
244
260
 
fmtr/tools/version CHANGED
@@ -1 +1 @@
1
- 1.1.3
1
+ 1.1.5
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmtr.tools
3
- Version: 1.1.3
3
+ Version: 1.1.5
4
4
  Summary: Collection of high-level tools to simplify everyday development tasks, with a focus on AI/ML
5
5
  Home-page: https://github.com/fmtr/fmtr.tools
6
6
  Author: Frontmatter
@@ -9,51 +9,51 @@ License: Copyright © 2025 Frontmatter. All rights reserved.
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
11
  Provides-Extra: test
12
+ Requires-Dist: pymupdf4llm; extra == "test"
13
+ Requires-Dist: pymupdf; extra == "test"
14
+ Requires-Dist: semver; extra == "test"
15
+ Requires-Dist: distributed; extra == "test"
16
+ Requires-Dist: fastapi; extra == "test"
17
+ Requires-Dist: pydantic-ai[logfire,openai]; extra == "test"
18
+ Requires-Dist: diskcache; extra == "test"
19
+ Requires-Dist: pandas; extra == "test"
20
+ Requires-Dist: contexttimer; extra == "test"
21
+ Requires-Dist: pytest-cov; extra == "test"
22
+ Requires-Dist: uvicorn[standard]; extra == "test"
12
23
  Requires-Dist: flet-webview; extra == "test"
13
- Requires-Dist: torchvision; extra == "test"
24
+ Requires-Dist: google-auth; extra == "test"
25
+ Requires-Dist: deepmerge; extra == "test"
26
+ Requires-Dist: flet-video; extra == "test"
14
27
  Requires-Dist: pydevd-pycharm; extra == "test"
15
- Requires-Dist: pytest-cov; extra == "test"
16
- Requires-Dist: ollama; extra == "test"
17
28
  Requires-Dist: torchaudio; extra == "test"
18
29
  Requires-Dist: faker; extra == "test"
19
- Requires-Dist: uvicorn[standard]; extra == "test"
20
- Requires-Dist: Unidecode; extra == "test"
21
- Requires-Dist: semver; extra == "test"
22
- Requires-Dist: openai; extra == "test"
23
- Requires-Dist: transformers[sentencepiece]; extra == "test"
24
- Requires-Dist: google-auth-httplib2; extra == "test"
25
- Requires-Dist: openpyxl; extra == "test"
30
+ Requires-Dist: bokeh; extra == "test"
26
31
  Requires-Dist: peft; extra == "test"
27
- Requires-Dist: docker; extra == "test"
28
- Requires-Dist: json_repair; extra == "test"
29
- Requires-Dist: dask[bag]; extra == "test"
30
- Requires-Dist: logfire[fastapi]; extra == "test"
31
- Requires-Dist: deepmerge; extra == "test"
32
- Requires-Dist: tinynetrc; extra == "test"
33
- Requires-Dist: sre_yield; extra == "test"
32
+ Requires-Dist: pydantic-settings; extra == "test"
33
+ Requires-Dist: logfire; extra == "test"
34
+ Requires-Dist: pyyaml; extra == "test"
34
35
  Requires-Dist: tabulate; extra == "test"
36
+ Requires-Dist: openpyxl; extra == "test"
37
+ Requires-Dist: google-api-python-client; extra == "test"
38
+ Requires-Dist: flet[all]; extra == "test"
39
+ Requires-Dist: transformers[sentencepiece]; extra == "test"
40
+ Requires-Dist: openai; extra == "test"
35
41
  Requires-Dist: sentence_transformers; extra == "test"
36
- Requires-Dist: google-auth; extra == "test"
37
- Requires-Dist: logfire; extra == "test"
42
+ Requires-Dist: google-auth-httplib2; extra == "test"
43
+ Requires-Dist: huggingface_hub; extra == "test"
44
+ Requires-Dist: dask[bag]; extra == "test"
38
45
  Requires-Dist: html2text; extra == "test"
39
- Requires-Dist: bokeh; extra == "test"
46
+ Requires-Dist: json_repair; extra == "test"
47
+ Requires-Dist: sre_yield; extra == "test"
48
+ Requires-Dist: logfire[fastapi]; extra == "test"
49
+ Requires-Dist: torchvision; extra == "test"
40
50
  Requires-Dist: pydantic; extra == "test"
41
- Requires-Dist: contexttimer; extra == "test"
42
- Requires-Dist: flet[all]; extra == "test"
43
- Requires-Dist: fastapi; extra == "test"
51
+ Requires-Dist: ollama; extra == "test"
52
+ Requires-Dist: Unidecode; extra == "test"
53
+ Requires-Dist: tinynetrc; extra == "test"
44
54
  Requires-Dist: google-auth-oauthlib; extra == "test"
45
- Requires-Dist: pandas; extra == "test"
46
- Requires-Dist: huggingface_hub; extra == "test"
47
- Requires-Dist: pymupdf; extra == "test"
48
- Requires-Dist: google-api-python-client; extra == "test"
49
- Requires-Dist: pydantic-settings; extra == "test"
50
- Requires-Dist: diskcache; extra == "test"
51
- Requires-Dist: distributed; extra == "test"
55
+ Requires-Dist: docker; extra == "test"
52
56
  Requires-Dist: tokenizers; extra == "test"
53
- Requires-Dist: flet-video; extra == "test"
54
- Requires-Dist: pyyaml; extra == "test"
55
- Requires-Dist: pydantic-ai[logfire,openai]; extra == "test"
56
- Requires-Dist: pymupdf4llm; extra == "test"
57
57
  Provides-Extra: yaml
58
58
  Requires-Dist: pyyaml; extra == "yaml"
59
59
  Provides-Extra: logging
@@ -4,7 +4,7 @@ fmtr/tools/async_tools.py,sha256=ewz757WcveQJd-G5SVr2JDOQVbdLGecCgl-tsBGVZz4,284
4
4
  fmtr/tools/augmentation_tools.py,sha256=-6ESbO4CDlKqVOV1J1V6qBeoBMzbFIinkDHRHnCBej0,55
5
5
  fmtr/tools/caching_tools.py,sha256=UOCYUNvLQ-NofR_dhqBmZF96-HRPf4At5MmxVk3gAIk,2943
6
6
  fmtr/tools/console_script_tools.py,sha256=Jcmm4WPhCQdPZfd468xD0epkt29sgcPROwKu79V_ehg,203
7
- fmtr/tools/constants.py,sha256=KrV6JpITZuVdLDN5ZzQb1wAAA3nNust6exCvbZEaKQE,1102
7
+ fmtr/tools/constants.py,sha256=vc7sa1WdEsaxqSxrRAKTmNv8EmtOoY3b_V9CtAx4zzw,1125
8
8
  fmtr/tools/data_modelling_tools.py,sha256=0BFm-F_cYzVTxftWQwORkPd0FM2BTLVh9-s0-rTTFoo,1744
9
9
  fmtr/tools/dataclass_tools.py,sha256=0Gt6KeLhtPgubo_2tYkIVqB8oQ91Qzag8OAGZDdjvMU,1209
10
10
  fmtr/tools/datatype_tools.py,sha256=3P4AWIFGkJ-UqvXlj0Jc9IvkIIgTOE9jRrOk3NVbpH8,1508
@@ -29,7 +29,7 @@ fmtr/tools/name_tools.py,sha256=5CB_phqhHjl66iI8oLxOGPF2odC1apdul-M8Fv2xBhs,5514
29
29
  fmtr/tools/netrc_tools.py,sha256=PpNpz_mWlQi6VHGromKwFfTyLpHUXsd4LY6-OKLCbeI,376
30
30
  fmtr/tools/openai_tools.py,sha256=6SUgejgzUzmlKKct2_ePXntvMegu3FJgfk9x7aqtqYc,742
31
31
  fmtr/tools/parallel_tools.py,sha256=QEb_gN1StkxsqYaH4HSjiJX8Y3gpb2uKNsOzG4uFpaM,3071
32
- fmtr/tools/path_tools.py,sha256=BKz9dVE2BTUzWKEc0_FuGzaWRowBbu1y0nwDk2blCi0,5861
32
+ fmtr/tools/path_tools.py,sha256=UNi_qRBugDHxBNdEm26wHy3UUBOfY6fVK_G1P51RfCI,6175
33
33
  fmtr/tools/pdf_tools.py,sha256=xvv9B84uAF81rFJRnXhSsxYuP42vY9ZdPVFrSMVe8G8,4069
34
34
  fmtr/tools/platform_tools.py,sha256=7p69CmAHe_sF68Fx9uVhns1k5EewTHTWgUYzkl6ZQKA,308
35
35
  fmtr/tools/process_tools.py,sha256=Ysh5Dk2QFBhXQerArjKdt7xZd3JrN5Ho02AaOjH0Nnw,1425
@@ -43,11 +43,11 @@ fmtr/tools/tabular_tools.py,sha256=tpIpZzYku1HcJrHZJL6BC39LmN3WUWVhFbK2N7nDVmE,1
43
43
  fmtr/tools/tokenization_tools.py,sha256=me-IBzSLyNYejLybwjO9CNB6Mj2NYfKPaOVThXyaGNg,4268
44
44
  fmtr/tools/tools.py,sha256=CAsApa1YwVdNE6H66Vjivs_mXYvOas3rh7fPELAnTpk,795
45
45
  fmtr/tools/unicode_tools.py,sha256=yS_9wpu8ogNoiIL7s1G_8bETFFO_YQlo4LNPv1NLDeY,52
46
- fmtr/tools/version,sha256=QVh-oXE9O_Eto7b8aIGNtIm6f6enRYGYzqERAJEy8sk,5
46
+ fmtr/tools/version,sha256=Iwbeq1q8AlvN6mQBfBIblRBrr3gUWq9O2jiD6Tl5zkg,5
47
47
  fmtr/tools/version_tools.py,sha256=yNs_CGqWpqE4jbK9wsPIi14peJVXYbhIcMqHAFOw3yE,1480
48
48
  fmtr/tools/yaml_tools.py,sha256=Ol43ZwbnSXGnn1K98Uxx61KPGSqfC4axE-X2q1LKMwk,349
49
49
  fmtr/tools/ai_tools/__init__.py,sha256=JZrLuOFNV1A3wvJgonxOgz_4WS-7MfCuowGWA5uYCjs,372
50
- fmtr/tools/ai_tools/agentic_tools.py,sha256=LMF7Udj8Nu7_l2VKeyDZRgY3F6GMP7CrrH9C7FTs-z8,2930
50
+ fmtr/tools/ai_tools/agentic_tools.py,sha256=pHmsWixulpIBEoIQvamfkQT9BDJ39unqS9ndVw0JVUw,3477
51
51
  fmtr/tools/ai_tools/inference_tools.py,sha256=yF8Oxph0L8W2CnK_o-MVztBhWVwBpgOEkx9_m3uqQww,11840
52
52
  fmtr/tools/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  fmtr/tools/tests/conftest.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -57,9 +57,9 @@ fmtr/tools/tests/test_environment.py,sha256=iHaiMQfECYZPkPKwfuIZV9uHuWe3aE-p_dN_
57
57
  fmtr/tools/tests/test_json.py,sha256=IeSP4ziPvRcmS8kq7k9tHonC9rN5YYq9GSNT2ul6Msk,287
58
58
  fmtr/tools/tests/test_path.py,sha256=AkZQa6_8BQ-VaCyL_J-iKmdf2ZaM-xFYR37Kun3k4_g,2188
59
59
  fmtr/tools/tests/test_yaml.py,sha256=jc0TwwKu9eC0LvFGNMERdgBue591xwLxYXFbtsRwXVM,287
60
- fmtr_tools-1.1.3.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
61
- fmtr_tools-1.1.3.dist-info/METADATA,sha256=wI0FdsdqtDsOhd2bmXV7Oiy-YezH6vW1ko-hh1KJ1VI,14646
62
- fmtr_tools-1.1.3.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
63
- fmtr_tools-1.1.3.dist-info/entry_points.txt,sha256=Zmeyls-zo5S99SlKUmsy9ULUNmk-4B9WQCEjuPIH0Yw,142
64
- fmtr_tools-1.1.3.dist-info/top_level.txt,sha256=t5341a8ii3n4RFizwTeXGmcq_pf4GqL1h9ylE5LIWRk,12
65
- fmtr_tools-1.1.3.dist-info/RECORD,,
60
+ fmtr_tools-1.1.5.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
61
+ fmtr_tools-1.1.5.dist-info/METADATA,sha256=Ag-YfPDiOUGjRQ1N9pIjtP9xXkIm4e4NBHlNw4d0rwI,14646
62
+ fmtr_tools-1.1.5.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
63
+ fmtr_tools-1.1.5.dist-info/entry_points.txt,sha256=Zmeyls-zo5S99SlKUmsy9ULUNmk-4B9WQCEjuPIH0Yw,142
64
+ fmtr_tools-1.1.5.dist-info/top_level.txt,sha256=t5341a8ii3n4RFizwTeXGmcq_pf4GqL1h9ylE5LIWRk,12
65
+ fmtr_tools-1.1.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5