dandy 2.1.0__tar.gz → 2.2.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.
Files changed (190) hide show
  1. {dandy-2.1.0 → dandy-2.2.0}/PKG-INFO +1 -1
  2. {dandy-2.1.0 → dandy-2.2.0}/dandy/constants.py +1 -1
  3. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/connector.py +15 -16
  4. dandy-2.2.0/dandy/llm/diligence/diligence.py +24 -0
  5. dandy-2.2.0/dandy/llm/diligence/handler.py +40 -0
  6. dandy-2.2.0/dandy/llm/diligence/mixin.py +12 -0
  7. dandy-2.2.0/dandy/llm/diligence/service.py +38 -0
  8. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/mixin.py +0 -5
  9. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/service.py +4 -1
  10. {dandy-2.1.0 → dandy-2.2.0}/dandy.egg-info/PKG-INFO +1 -1
  11. {dandy-2.1.0 → dandy-2.2.0}/dandy.egg-info/SOURCES.txt +2 -0
  12. {dandy-2.1.0 → dandy-2.2.0}/pyproject.toml +0 -6
  13. dandy-2.1.0/dandy/llm/diligence/diligence.py +0 -31
  14. dandy-2.1.0/dandy/llm/diligence/handler.py +0 -44
  15. {dandy-2.1.0 → dandy-2.2.0}/LICENSE.md +0 -0
  16. {dandy-2.1.0 → dandy-2.2.0}/README.md +0 -0
  17. {dandy-2.1.0 → dandy-2.2.0}/dandy/__init__.py +0 -0
  18. {dandy-2.1.0 → dandy-2.2.0}/dandy/bot/__init__.py +0 -0
  19. {dandy-2.1.0 → dandy-2.2.0}/dandy/bot/bot.py +0 -0
  20. {dandy-2.1.0 → dandy-2.2.0}/dandy/bot/exceptions.py +0 -0
  21. {dandy-2.1.0 → dandy-2.2.0}/dandy/bot/recorder.py +0 -0
  22. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/__init__.py +0 -0
  23. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/cache.py +0 -0
  24. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/decorators.py +0 -0
  25. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/exceptions.py +0 -0
  26. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/memory/__init__.py +0 -0
  27. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/memory/cache.py +0 -0
  28. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/memory/decorators.py +0 -0
  29. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/sqlite/__init__.py +0 -0
  30. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/sqlite/cache.py +0 -0
  31. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/sqlite/connection.py +0 -0
  32. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/sqlite/decorators.py +0 -0
  33. {dandy-2.1.0 → dandy-2.2.0}/dandy/cache/tools.py +0 -0
  34. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/__init__.py +0 -0
  35. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/__init__.py +0 -0
  36. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/action.py +0 -0
  37. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/bot/__init__.py +0 -0
  38. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/bot/action.py +0 -0
  39. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/code/__init__.py +0 -0
  40. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/code/action.py +0 -0
  41. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/code/intelligence/__init__.py +0 -0
  42. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/code/intelligence/bots/__init__.py +0 -0
  43. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/code/intelligence/bots/coding_bot.py +0 -0
  44. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/constants.py +0 -0
  45. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/__init__.py +0 -0
  46. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/action.py +0 -0
  47. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/intelligence/__init__.py +0 -0
  48. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/intelligence/bots/__init__.py +0 -0
  49. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/intelligence/bots/code_explainer_bot.py +0 -0
  50. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/intelligence/decoders/__init__.py +0 -0
  51. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/intelligence/decoders/files_decoder.py +0 -0
  52. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/intelligence/intel/__init__.py +0 -0
  53. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/explain/intelligence/workflow.py +0 -0
  54. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/help/__init__.py +0 -0
  55. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/help/action.py +0 -0
  56. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/help/intelligence/__init__.py +0 -0
  57. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/help/intelligence/bots/__init__.py +0 -0
  58. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/help/intelligence/bots/default_user_input_bot.py +0 -0
  59. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/help/intelligence/intel/__init__.py +0 -0
  60. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/help/intelligence/intel/default_user_input_intel.py +0 -0
  61. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/help/intelligence/prompt.py +0 -0
  62. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/manager.py +0 -0
  63. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/quit/__init__.py +0 -0
  64. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/actions/quit/action.py +0 -0
  65. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/cli.py +0 -0
  66. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/intelligence/__init__.py +0 -0
  67. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/intelligence/bots/__init__.py +0 -0
  68. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/intelligence/bots/source_code_bot.py +0 -0
  69. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/intelligence/intel/__init__.py +0 -0
  70. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/intelligence/intel/source_code_intel.py +0 -0
  71. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/main.py +0 -0
  72. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/processing_phrases.py +0 -0
  73. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/session.py +0 -0
  74. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/tui/__init__.py +0 -0
  75. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/tui/ascii.py +0 -0
  76. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/tui/printer.py +0 -0
  77. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/tui/tools.py +0 -0
  78. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/tui/tui.py +0 -0
  79. {dandy-2.1.0 → dandy-2.2.0}/dandy/cli/utils.py +0 -0
  80. {dandy-2.1.0 → dandy-2.2.0}/dandy/conf.py +0 -0
  81. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/__init__.py +0 -0
  82. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/connector/__init__.py +0 -0
  83. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/connector/connector.py +0 -0
  84. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/connector/exceptions.py +0 -0
  85. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/debug.py +0 -0
  86. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/exceptions.py +0 -0
  87. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/future/__init__.py +0 -0
  88. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/future/exceptions.py +0 -0
  89. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/future/future.py +0 -0
  90. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/future/tools.py +0 -0
  91. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/service/__init__.py +0 -0
  92. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/service/exceptions.py +0 -0
  93. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/service/mixin.py +0 -0
  94. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/service/service.py +0 -0
  95. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/singleton.py +0 -0
  96. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/typing/__init__.py +0 -0
  97. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/typing/constants.py +0 -0
  98. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/typing/exceptions.py +0 -0
  99. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/typing/registry.py +0 -0
  100. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/typing/tools.py +0 -0
  101. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/typing/typed_kwargs.py +0 -0
  102. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/typing/typing.py +0 -0
  103. {dandy-2.1.0 → dandy-2.2.0}/dandy/core/utils.py +0 -0
  104. {dandy-2.1.0 → dandy-2.2.0}/dandy/default_settings.py +0 -0
  105. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/__init__.py +0 -0
  106. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/audio/__init__.py +0 -0
  107. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/audio/constants.py +0 -0
  108. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/audio/utils.py +0 -0
  109. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/exceptions.py +0 -0
  110. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/image/__init__.py +0 -0
  111. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/image/constants.py +0 -0
  112. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/image/utils.py +0 -0
  113. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/mixin.py +0 -0
  114. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/service.py +0 -0
  115. {dandy-2.1.0 → dandy-2.2.0}/dandy/file/utils.py +0 -0
  116. {dandy-2.1.0 → dandy-2.2.0}/dandy/http/__init__.py +0 -0
  117. {dandy-2.1.0 → dandy-2.2.0}/dandy/http/connector.py +0 -0
  118. {dandy-2.1.0 → dandy-2.2.0}/dandy/http/exceptions.py +0 -0
  119. {dandy-2.1.0 → dandy-2.2.0}/dandy/http/intelligence/__init__.py +0 -0
  120. {dandy-2.1.0 → dandy-2.2.0}/dandy/http/intelligence/intel.py +0 -0
  121. {dandy-2.1.0 → dandy-2.2.0}/dandy/http/mixin.py +0 -0
  122. {dandy-2.1.0 → dandy-2.2.0}/dandy/http/service.py +0 -0
  123. {dandy-2.1.0 → dandy-2.2.0}/dandy/http/url.py +0 -0
  124. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/__init__.py +0 -0
  125. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/exceptions.py +0 -0
  126. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/factory.py +0 -0
  127. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/field/__init__.py +0 -0
  128. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/field/annotation.py +0 -0
  129. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/intel.py +0 -0
  130. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/mixin.py +0 -0
  131. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/service.py +0 -0
  132. {dandy-2.1.0 → dandy-2.2.0}/dandy/intel/typing.py +0 -0
  133. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/__init__.py +0 -0
  134. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/config.py +0 -0
  135. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/__init__.py +0 -0
  136. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/decoder.py +0 -0
  137. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/exceptions.py +0 -0
  138. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/intel.py +0 -0
  139. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/intelligence/__init__.py +0 -0
  140. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/intelligence/prompts.py +0 -0
  141. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/mixin.py +0 -0
  142. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/recorder.py +0 -0
  143. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/decoder/service.py +0 -0
  144. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/__init__.py +0 -0
  145. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/recorder.py +0 -0
  146. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/second_pass/__init__.py +0 -0
  147. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/second_pass/diligence.py +0 -0
  148. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/stop_word_removal/__init__.py +0 -0
  149. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/stop_word_removal/constants.py +0 -0
  150. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/stop_word_removal/diligence.py +0 -0
  151. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/vowel_removal/__init__.py +0 -0
  152. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/vowel_removal/constants.py +0 -0
  153. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/diligence/vowel_removal/diligence.py +0 -0
  154. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/exceptions.py +0 -0
  155. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/intelligence/__init__.py +0 -0
  156. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/intelligence/prompts.py +0 -0
  157. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/options.py +0 -0
  158. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/prompt/__init__.py +0 -0
  159. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/prompt/prompt.py +0 -0
  160. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/prompt/snippet.py +0 -0
  161. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/prompt/tools.py +0 -0
  162. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/recorder.py +0 -0
  163. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/request/__init__.py +0 -0
  164. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/request/message.py +0 -0
  165. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/request/request.py +0 -0
  166. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/tokens/__init__.py +0 -0
  167. {dandy-2.1.0 → dandy-2.2.0}/dandy/llm/tokens/utils.py +0 -0
  168. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/__init__.py +0 -0
  169. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/decorators.py +0 -0
  170. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/events.py +0 -0
  171. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/exceptions.py +0 -0
  172. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/recorder.py +0 -0
  173. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/recording.py +0 -0
  174. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/renderer/__init__.py +0 -0
  175. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/renderer/html.py +0 -0
  176. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/renderer/html_templates/base_event_template.html +0 -0
  177. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/renderer/html_templates/base_recording_output_template.html +0 -0
  178. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/renderer/json.py +0 -0
  179. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/renderer/markdown.py +0 -0
  180. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/renderer/renderer.py +0 -0
  181. {dandy-2.1.0 → dandy-2.2.0}/dandy/recorder/utils.py +0 -0
  182. {dandy-2.1.0 → dandy-2.2.0}/dandy/tool/__init__.py +0 -0
  183. {dandy-2.1.0 → dandy-2.2.0}/dandy/tool/git/__init__.py +0 -0
  184. {dandy-2.1.0 → dandy-2.2.0}/dandy/tool/git/tool.py +0 -0
  185. {dandy-2.1.0 → dandy-2.2.0}/dandy/tool/tool.py +0 -0
  186. {dandy-2.1.0 → dandy-2.2.0}/dandy.egg-info/dependency_links.txt +0 -0
  187. {dandy-2.1.0 → dandy-2.2.0}/dandy.egg-info/entry_points.txt +0 -0
  188. {dandy-2.1.0 → dandy-2.2.0}/dandy.egg-info/requires.txt +0 -0
  189. {dandy-2.1.0 → dandy-2.2.0}/dandy.egg-info/top_level.txt +0 -0
  190. {dandy-2.1.0 → dandy-2.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dandy
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Python Artificial Intelligence Framework
5
5
  Author-email: Nathan Johnson <nathanj@stratusadv.com>
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- __VERSION__ = '2.1.0'
1
+ __VERSION__ = '2.2.0'
2
2
 
3
3
  # Cache
4
4
 
@@ -1,4 +1,7 @@
1
+ from __future__ import annotations
2
+
1
3
  from pathlib import Path
4
+ from typing import TYPE_CHECKING
2
5
 
3
6
  from pydantic import ValidationError
4
7
  from pydantic.main import IncEx
@@ -8,11 +11,6 @@ from dandy.http.connector import HttpConnector
8
11
  from dandy.intel.factory import IntelFactory
9
12
  from dandy.intel.typing import IntelType
10
13
  from dandy.llm.config import LlmConfig
11
- from dandy.llm.diligence.handler import (
12
- BaseDiligenceHandler,
13
- PreDiligenceHandler,
14
- PostDiligenceHandler,
15
- )
16
14
  from dandy.llm.exceptions import LlmCriticalError, LlmRecoverableError
17
15
  from dandy.llm.intelligence.prompts import service_system_validation_error_prompt
18
16
  from dandy.llm.prompt.prompt import Prompt
@@ -25,6 +23,9 @@ from dandy.llm.recorder import (
25
23
  )
26
24
  from dandy.llm.request.message import MessageHistory
27
25
 
26
+ if TYPE_CHECKING:
27
+ from dandy.llm.diligence.handler import DiligenceHandler
28
+
28
29
 
29
30
  class LlmConnector(BaseConnector):
30
31
  def __init__(
@@ -33,7 +34,8 @@ class LlmConnector(BaseConnector):
33
34
  llm_config: LlmConfig,
34
35
  intel_class: type[IntelType] | None,
35
36
  system_prompt: Prompt | str,
36
- diligence: float = 1.0,
37
+ post_diligence_handler: DiligenceHandler | None = None,
38
+ pre_diligence_handler: DiligenceHandler | None = None,
37
39
  ):
38
40
  self.recorder_event_id = recorder_event_id
39
41
 
@@ -49,16 +51,13 @@ class LlmConnector(BaseConnector):
49
51
 
50
52
  self.system_prompt_str = str(system_prompt)
51
53
 
52
- self.diligence = diligence
54
+ self.post_diligence_handler = post_diligence_handler
55
+ self.pre_diligence_handler = pre_diligence_handler
53
56
 
54
57
  @property
55
58
  def has_retry_attempts_available(self) -> bool:
56
59
  return self.prompt_retry_attempt < self.llm_config.options.prompt_retry_count
57
60
 
58
- @property
59
- def _changed_diligence(self) -> bool:
60
- return self.diligence != 1.0
61
-
62
61
  def _http_request_to_response_str(self) -> None:
63
62
  http_connector = HttpConnector()
64
63
 
@@ -131,15 +130,15 @@ class LlmConnector(BaseConnector):
131
130
  )
132
131
  raise LlmCriticalError(message)
133
132
 
134
- if self._changed_diligence:
135
- PreDiligenceHandler(level=self.diligence).apply(llm_connector=self)
133
+ if self.pre_diligence_handler is not None:
134
+ self.pre_diligence_handler.apply(llm_connector=self)
136
135
 
137
136
  response_intel_object = self._request_to_intel()
138
137
 
139
- if self._changed_diligence:
140
- PostDiligenceHandler(level=self.diligence).apply(llm_connector=self)
138
+ if self.post_diligence_handler is not None:
139
+ self.post_diligence_handler.apply(llm_connector=self)
141
140
 
142
- if PostDiligenceHandler(level=self.diligence).requires_new_llm_request:
141
+ if self.post_diligence_handler.requires_new_llm_request:
143
142
  response_intel_object = self._request_to_intel()
144
143
 
145
144
  return response_intel_object
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from dandy.llm.connector import LlmConnector
8
+
9
+
10
+ class BaseDiligence(ABC):
11
+ requires_new_llm_request: bool = False
12
+
13
+ def __init__(self):
14
+ self.is_activated = False
15
+
16
+ def activate(self) -> None:
17
+ self.is_activated = True
18
+
19
+ def deactivate(self) -> None:
20
+ self.is_activated = False
21
+
22
+ @abstractmethod
23
+ def apply(self, llm_connector: LlmConnector) -> None:
24
+ raise NotImplementedError
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, TypeVar
4
+
5
+ if TYPE_CHECKING:
6
+ from dandy.llm.connector import LlmConnector
7
+ from dandy.llm.diligence.diligence import BaseDiligence
8
+
9
+ DiligenceType = TypeVar('DiligenceType', bound='BaseDiligence')
10
+
11
+
12
+ class DiligenceHandler:
13
+ def __init__(self) -> None:
14
+ self._diligence_classes_instances: dict[type[BaseDiligence], BaseDiligence] = {}
15
+
16
+ @property
17
+ def is_activated(self) -> bool:
18
+ if not self._diligence_classes_instances:
19
+ return False
20
+
21
+ return any(diligence.is_activated for diligence in self._diligence_classes_instances.values())
22
+
23
+ def apply(self, llm_connector: LlmConnector) -> None:
24
+ for diligence in self._diligence_classes_instances.values():
25
+ if diligence.is_activated:
26
+ diligence.apply(llm_connector=llm_connector)
27
+
28
+ def get_diligence(self, diligence_class: type[DiligenceType]) -> DiligenceType:
29
+ if diligence_class not in self._diligence_classes_instances:
30
+ self._diligence_classes_instances[diligence_class] = diligence_class()
31
+
32
+ return self._diligence_classes_instances[diligence_class]
33
+
34
+ @property
35
+ def requires_new_llm_request(self) -> bool:
36
+ for diligence in self._diligence_classes_instances.values():
37
+ if diligence.is_activated and diligence.requires_new_llm_request:
38
+ return True
39
+
40
+ return False
@@ -0,0 +1,12 @@
1
+ from dandy.core.service.mixin import BaseServiceMixin
2
+ from dandy.llm.diligence.service import DiligenceService
3
+
4
+
5
+ class DiligenceServiceMixin(BaseServiceMixin):
6
+ @property
7
+ def diligence(self) -> DiligenceService:
8
+ return self._get_service_instance(DiligenceService)
9
+
10
+ def reset(self):
11
+ super().reset()
12
+ self.diligence.reset()
@@ -0,0 +1,38 @@
1
+ from dandy.core.service.service import BaseService
2
+ from dandy.llm.diligence.diligence import BaseDiligence
3
+ from dandy.llm.diligence.handler import DiligenceHandler
4
+ from dandy.llm.diligence.second_pass.diligence import SecondPassRemovalDiligence
5
+ from dandy.llm.diligence.stop_word_removal.diligence import StopWordRemovalDiligence
6
+ from dandy.llm.diligence.vowel_removal.diligence import VowelRemovalDiligence
7
+
8
+
9
+ class DiligenceService(BaseService['dandy.llm.diligence.mixin.DiligenceServiceMixin']):
10
+ def __post_init__(self):
11
+ self.post_handler: DiligenceHandler = None
12
+ self.pre_handler: DiligenceHandler = None
13
+ self._reset_handlers()
14
+
15
+ def _reset_handlers(self):
16
+ self.post_handler: DiligenceHandler = DiligenceHandler()
17
+ self.pre_handler: DiligenceHandler = DiligenceHandler()
18
+
19
+ @property
20
+ def second_pass(self) -> SecondPassRemovalDiligence:
21
+ return self.post_handler.get_diligence(
22
+ SecondPassRemovalDiligence
23
+ )
24
+
25
+ @property
26
+ def stop_word_removal(self) -> StopWordRemovalDiligence:
27
+ return self.post_handler.get_diligence(
28
+ StopWordRemovalDiligence
29
+ )
30
+
31
+ @property
32
+ def vowel_removal(self) -> VowelRemovalDiligence:
33
+ return self.pre_handler.get_diligence(
34
+ VowelRemovalDiligence
35
+ )
36
+
37
+ def reset(self):
38
+ self._reset_handlers()
@@ -8,7 +8,6 @@ from dandy.llm.service import LlmService
8
8
 
9
9
 
10
10
  class LlmServiceMixin(BaseServiceMixin):
11
- diligence: float = 1.0
12
11
  llm_config: str = 'DEFAULT'
13
12
  intel_class: type[BaseIntel] = DefaultIntel
14
13
  role: Prompt | str = 'Assistant'
@@ -29,7 +28,6 @@ class LlmServiceMixin(BaseServiceMixin):
29
28
  role: Prompt | str | None = None,
30
29
  task: Prompt | str | None = None,
31
30
  guidelines: Prompt | str | None = None,
32
- diligence: float | None = None,
33
31
  llm_config: str | None = None,
34
32
  llm_temperature: float | None = None,
35
33
  **kwargs,
@@ -45,9 +43,6 @@ class LlmServiceMixin(BaseServiceMixin):
45
43
  if isinstance(guidelines, (Prompt, str)):
46
44
  self.guidelines = guidelines
47
45
 
48
- if isinstance(diligence, float):
49
- self.diligence = diligence
50
-
51
46
  if isinstance(llm_config, str):
52
47
  self.llm_config = llm_config
53
48
 
@@ -7,6 +7,7 @@ from dandy.core.future.tools import process_to_future
7
7
  from dandy.core.service.service import BaseService
8
8
  from dandy.llm.connector import LlmConnector
9
9
  from dandy.llm.decoder.mixin import DecoderServiceMixin
10
+ from dandy.llm.diligence.mixin import DiligenceServiceMixin
10
11
  from dandy.llm.intelligence.prompts import service_system_prompt
11
12
 
12
13
  if TYPE_CHECKING:
@@ -22,11 +23,11 @@ if TYPE_CHECKING:
22
23
  class LlmService(
23
24
  BaseService['dandy.llm.mixin.LlmServiceMixin'],
24
25
  DecoderServiceMixin,
26
+ DiligenceServiceMixin,
25
27
  ):
26
28
  def __post_init__(self):
27
29
  self._llm_connector: LlmConnector = LlmConnector(
28
30
  recorder_event_id=self.recorder_event_id,
29
- diligence=self.obj.diligence,
30
31
  system_prompt=service_system_prompt(
31
32
  role=self.obj.role,
32
33
  task=self.obj.task,
@@ -35,6 +36,8 @@ class LlmService(
35
36
  ).to_str(),
36
37
  llm_config=self.obj.get_llm_config(),
37
38
  intel_class=self.obj.intel_class,
39
+ post_diligence_handler=self.diligence.post_handler,
40
+ pre_diligence_handler=self.diligence.pre_handler,
38
41
  )
39
42
 
40
43
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dandy
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Python Artificial Intelligence Framework
5
5
  Author-email: Nathan Johnson <nathanj@stratusadv.com>
6
6
  License-Expression: MIT
@@ -144,7 +144,9 @@ dandy/llm/decoder/intelligence/prompts.py
144
144
  dandy/llm/diligence/__init__.py
145
145
  dandy/llm/diligence/diligence.py
146
146
  dandy/llm/diligence/handler.py
147
+ dandy/llm/diligence/mixin.py
147
148
  dandy/llm/diligence/recorder.py
149
+ dandy/llm/diligence/service.py
148
150
  dandy/llm/diligence/second_pass/__init__.py
149
151
  dandy/llm/diligence/second_pass/diligence.py
150
152
  dandy/llm/diligence/stop_word_removal/__init__.py
@@ -88,12 +88,6 @@ dandy = [
88
88
  [tool.setuptools.dynamic]
89
89
  version = { attr = "dandy.constants.__VERSION__" }
90
90
 
91
- [tool.ruff]
92
- extend = "ruff.toml"
93
-
94
- [tool.ty]
95
- extend = "ty.toml"
96
-
97
91
  [tool.codespell]
98
92
  # Ref: https://github.com/codespell-project/codespell#using-a-config-file
99
93
  skip = '.git*,*.svg,*.css,.cache,.npm'
@@ -1,31 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from abc import ABC, abstractmethod
4
- from typing import Callable, TYPE_CHECKING
5
-
6
- if TYPE_CHECKING:
7
- from dandy.llm.connector import LlmConnector
8
-
9
-
10
- class BaseDiligence(ABC):
11
- trigger_level: float
12
- trigger_operator: Callable[[float, float], bool]
13
- requires_new_llm_request: bool = False
14
-
15
- def __init_subclass__(cls, **kwargs) -> None:
16
- if (
17
- cls.trigger_level == 1.0
18
- or cls.trigger_level > 2.0
19
- or cls.trigger_level < 0.0
20
- ):
21
- message = f"`{cls.__name__}` should have a trigger level between 0.0 and 2.0 and not 1.0 as it's used as the default."
22
- raise ValueError(message)
23
-
24
- @classmethod
25
- def is_triggered(cls, level: float) -> bool:
26
- return cls.trigger_operator(level, cls.trigger_level)
27
-
28
- @classmethod
29
- @abstractmethod
30
- def apply(cls, llm_connector: LlmConnector) -> None:
31
- raise NotImplementedError
@@ -1,44 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from abc import ABC
4
- from typing import TYPE_CHECKING
5
-
6
- from dandy.llm.diligence.second_pass.diligence import SecondPassRemovalDiligence
7
- from dandy.llm.diligence.stop_word_removal.diligence import StopWordRemovalDiligence
8
- from dandy.llm.diligence.vowel_removal.diligence import VowelRemovalDiligence
9
-
10
- if TYPE_CHECKING:
11
- from dandy.llm.connector import LlmConnector
12
- from dandy.llm.diligence.diligence import BaseDiligence
13
-
14
-
15
- class BaseDiligenceHandler(ABC):
16
- diligence_classes: tuple[type[BaseDiligence]]
17
-
18
- def __init__(self, level: float) -> None:
19
- self.level = level
20
-
21
- def apply(self, llm_connector: LlmConnector) -> None:
22
- for diligence_class in self.diligence_classes:
23
- if diligence_class.is_triggered(self.level):
24
- diligence_class.apply(llm_connector=llm_connector)
25
-
26
- @property
27
- def requires_new_llm_request(self) -> bool:
28
- for diligence_class in self.diligence_classes:
29
- if diligence_class.is_triggered(self.level) and diligence_class.requires_new_llm_request:
30
- return True
31
-
32
- return False
33
-
34
-
35
-
36
- class PreDiligenceHandler(BaseDiligenceHandler):
37
- diligence_classes = (
38
- StopWordRemovalDiligence,
39
- VowelRemovalDiligence,
40
- )
41
-
42
-
43
- class PostDiligenceHandler(BaseDiligenceHandler):
44
- diligence_classes = (SecondPassRemovalDiligence,)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes