django-spire 0.16.11__py3-none-any.whl → 0.16.13__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.
Files changed (148) hide show
  1. django_spire/ai/admin.py +3 -1
  2. django_spire/ai/apps.py +2 -0
  3. django_spire/ai/chat/admin.py +15 -9
  4. django_spire/ai/chat/apps.py +4 -1
  5. django_spire/ai/chat/auth/controller.py +3 -1
  6. django_spire/ai/chat/choices.py +2 -0
  7. django_spire/ai/chat/intelligence/maps/intent_llm_map.py +8 -5
  8. django_spire/ai/chat/intelligence/prompts.py +4 -2
  9. django_spire/ai/chat/intelligence/workflows/chat_workflow.py +27 -28
  10. django_spire/ai/chat/message_intel.py +7 -4
  11. django_spire/ai/chat/models.py +8 -9
  12. django_spire/ai/chat/querysets.py +3 -1
  13. django_spire/ai/chat/responses.py +19 -10
  14. django_spire/ai/chat/tools.py +20 -15
  15. django_spire/ai/chat/urls/message_urls.py +2 -1
  16. django_spire/ai/chat/urls/page_urls.py +1 -0
  17. django_spire/ai/chat/views/message_request_views.py +2 -0
  18. django_spire/ai/chat/views/message_response_views.py +4 -4
  19. django_spire/ai/chat/views/message_views.py +2 -0
  20. django_spire/ai/chat/views/page_views.py +7 -2
  21. django_spire/ai/chat/views/template_views.py +2 -0
  22. django_spire/ai/decorators.py +13 -7
  23. django_spire/ai/mixins.py +4 -2
  24. django_spire/ai/models.py +7 -2
  25. django_spire/ai/prompt/bots.py +14 -32
  26. django_spire/ai/prompt/intel.py +1 -1
  27. django_spire/ai/prompt/prompts.py +7 -1
  28. django_spire/ai/prompt/system/bots.py +42 -75
  29. django_spire/ai/prompt/system/intel.py +5 -4
  30. django_spire/ai/prompt/system/prompts.py +5 -1
  31. django_spire/ai/prompt/system/system_prompt_cli.py +15 -9
  32. django_spire/ai/prompt/tests/test_bots.py +14 -11
  33. django_spire/ai/prompt/text_to_prompt_cli.py +5 -2
  34. django_spire/ai/prompt/tuning/bot_tuning_cli.py +14 -13
  35. django_spire/ai/prompt/tuning/bots.py +68 -116
  36. django_spire/ai/prompt/tuning/intel.py +1 -1
  37. django_spire/ai/prompt/tuning/mixins.py +2 -0
  38. django_spire/ai/prompt/tuning/prompt_tuning_cli.py +8 -8
  39. django_spire/ai/prompt/tuning/prompts.py +4 -2
  40. django_spire/ai/sms/admin.py +3 -1
  41. django_spire/ai/sms/apps.py +2 -0
  42. django_spire/ai/sms/decorators.py +2 -0
  43. django_spire/ai/sms/intel.py +4 -2
  44. django_spire/ai/sms/intelligence/workflows/sms_conversation_workflow.py +8 -8
  45. django_spire/ai/sms/models.py +16 -14
  46. django_spire/ai/sms/querysets.py +4 -1
  47. django_spire/ai/sms/tools.py +18 -16
  48. django_spire/ai/sms/urls.py +1 -1
  49. django_spire/ai/sms/views.py +2 -0
  50. django_spire/ai/tests/test_ai.py +3 -5
  51. django_spire/ai/urls.py +1 -0
  52. django_spire/consts.py +1 -1
  53. django_spire/contrib/seeding/field/django/seeder.py +6 -4
  54. django_spire/contrib/seeding/field/llm.py +1 -2
  55. django_spire/contrib/seeding/intelligence/bots/field_seeding_bots.py +7 -8
  56. django_spire/contrib/seeding/intelligence/bots/seeder_generator_bot.py +15 -16
  57. django_spire/contrib/seeding/intelligence/intel.py +1 -1
  58. django_spire/contrib/seeding/intelligence/prompts/factory.py +5 -7
  59. django_spire/contrib/seeding/intelligence/prompts/foreign_key_selection_prompt.py +3 -5
  60. django_spire/contrib/seeding/intelligence/prompts/generate_django_model_seeder_prompts.py +1 -2
  61. django_spire/contrib/seeding/intelligence/prompts/generic_relationship_selection_prompt.py +3 -5
  62. django_spire/contrib/seeding/intelligence/prompts/hierarchical_selection_prompt.py +1 -1
  63. django_spire/contrib/seeding/intelligence/prompts/model_field_choices_prompt.py +3 -3
  64. django_spire/contrib/seeding/intelligence/prompts/negation_prompt.py +1 -1
  65. django_spire/contrib/seeding/intelligence/prompts/objective_prompt.py +2 -4
  66. django_spire/contrib/seeding/management/commands/seeding.py +5 -2
  67. django_spire/contrib/seeding/model/base.py +12 -10
  68. django_spire/contrib/seeding/model/django/seeder.py +13 -10
  69. django_spire/contrib/seeding/tests/test_seeding.py +1 -1
  70. django_spire/file/apps.py +13 -0
  71. django_spire/file/interfaces.py +42 -9
  72. django_spire/knowledge/admin.py +2 -0
  73. django_spire/knowledge/apps.py +2 -0
  74. django_spire/knowledge/auth/controller.py +2 -0
  75. django_spire/knowledge/collection/admin.py +3 -0
  76. django_spire/knowledge/collection/forms.py +2 -0
  77. django_spire/knowledge/collection/models.py +4 -0
  78. django_spire/knowledge/collection/querysets.py +3 -3
  79. django_spire/knowledge/collection/seeding/seed.py +2 -0
  80. django_spire/knowledge/collection/tests/factories.py +2 -0
  81. django_spire/knowledge/collection/tests/test_services/test_transformation_service.py +2 -0
  82. django_spire/knowledge/collection/tests/test_urls/test_form_urls.py +2 -0
  83. django_spire/knowledge/collection/tests/test_urls/test_json_urls.py +2 -0
  84. django_spire/knowledge/collection/tests/test_urls/test_page_urls.py +2 -0
  85. django_spire/knowledge/collection/views/json_views.py +2 -0
  86. django_spire/knowledge/collection/views/page_views.py +2 -0
  87. django_spire/knowledge/context_processors.py +2 -0
  88. django_spire/knowledge/entry/services/automation_service.py +2 -4
  89. django_spire/knowledge/entry/services/factory_service.py +1 -2
  90. django_spire/knowledge/entry/services/tool_service.py +2 -2
  91. django_spire/knowledge/entry/services/transformation_services.py +0 -1
  92. django_spire/knowledge/entry/tests/factories.py +3 -0
  93. django_spire/knowledge/entry/tests/test_urls/test_form_urls.py +2 -0
  94. django_spire/knowledge/entry/tests/test_urls/test_json_urls.py +2 -0
  95. django_spire/knowledge/entry/tests/test_urls/test_page_urls.py +2 -0
  96. django_spire/knowledge/entry/urls/form_urls.py +1 -0
  97. django_spire/knowledge/entry/urls/json_urls.py +1 -0
  98. django_spire/knowledge/entry/urls/page_urls.py +1 -0
  99. django_spire/knowledge/entry/urls/template_urls.py +1 -0
  100. django_spire/knowledge/entry/version/admin.py +2 -0
  101. django_spire/knowledge/entry/version/block/admin.py +2 -0
  102. django_spire/knowledge/entry/version/block/blocks/heading_block.py +2 -0
  103. django_spire/knowledge/entry/version/block/blocks/sub_heading_block.py +2 -0
  104. django_spire/knowledge/entry/version/block/blocks/text_block.py +2 -0
  105. django_spire/knowledge/entry/version/block/maps.py +2 -0
  106. django_spire/knowledge/entry/version/block/models.py +2 -0
  107. django_spire/knowledge/entry/version/block/tests/factories.py +2 -0
  108. django_spire/knowledge/entry/version/block/tests/test_urls/test_json_urls.py +2 -0
  109. django_spire/knowledge/entry/version/block/views/json_views.py +2 -0
  110. django_spire/knowledge/entry/version/converters/docx_converter.py +1 -1
  111. django_spire/knowledge/entry/version/converters/markdown_converter.py +2 -1
  112. django_spire/knowledge/entry/version/intelligence/bots/markdown_format_llm_bot.py +12 -9
  113. django_spire/knowledge/entry/version/maps.py +2 -0
  114. django_spire/knowledge/entry/version/models.py +2 -0
  115. django_spire/knowledge/entry/version/querysets.py +2 -0
  116. django_spire/knowledge/entry/version/seeding/seeder.py +1 -0
  117. django_spire/knowledge/entry/version/tests/factories.py +2 -0
  118. django_spire/knowledge/entry/version/tests/test_converters/test_docx_converter.py +3 -0
  119. django_spire/knowledge/entry/version/tests/test_urls/test_form_urls.py +2 -0
  120. django_spire/knowledge/entry/version/tests/test_urls/test_json_urls.py +2 -0
  121. django_spire/knowledge/entry/version/tests/test_urls/test_page_urls.py +2 -0
  122. django_spire/knowledge/entry/version/urls/form_urls.py +1 -0
  123. django_spire/knowledge/entry/version/urls/json_urls.py +1 -0
  124. django_spire/knowledge/entry/version/urls/page_urls.py +1 -0
  125. django_spire/knowledge/entry/version/urls/redirect_urls.py +1 -0
  126. django_spire/knowledge/entry/version/views/form_views.py +2 -0
  127. django_spire/knowledge/entry/version/views/json_views.py +2 -0
  128. django_spire/knowledge/entry/version/views/page_views.py +2 -0
  129. django_spire/knowledge/entry/version/views/redirect_views.py +2 -0
  130. django_spire/knowledge/entry/views/form_views.py +4 -2
  131. django_spire/knowledge/exceptions.py +2 -0
  132. django_spire/knowledge/intelligence/bots/entry_search_llm_bot.py +5 -16
  133. django_spire/knowledge/intelligence/intel/collection_intel.py +3 -1
  134. django_spire/knowledge/intelligence/intel/entry_intel.py +3 -3
  135. django_spire/knowledge/intelligence/intel/message_intel.py +2 -0
  136. django_spire/knowledge/intelligence/maps/collection_map.py +9 -10
  137. django_spire/knowledge/intelligence/maps/entry_map.py +8 -9
  138. django_spire/knowledge/intelligence/workflows/knowledge_workflow.py +8 -6
  139. django_spire/knowledge/models.py +2 -0
  140. django_spire/knowledge/seeding/seed.py +2 -0
  141. django_spire/knowledge/templatetags/spire_knowledge_tags.py +3 -0
  142. django_spire/knowledge/urls/__init__.py +1 -0
  143. {django_spire-0.16.11.dist-info → django_spire-0.16.13.dist-info}/METADATA +7 -2
  144. {django_spire-0.16.11.dist-info → django_spire-0.16.13.dist-info}/RECORD +147 -148
  145. django_spire/knowledge/entry/tests/constants.py +0 -1
  146. {django_spire-0.16.11.dist-info → django_spire-0.16.13.dist-info}/WHEEL +0 -0
  147. {django_spire-0.16.11.dist-info → django_spire-0.16.13.dist-info}/licenses/LICENSE.md +0 -0
  148. {django_spire-0.16.11.dist-info → django_spire-0.16.13.dist-info}/top_level.txt +0 -0
@@ -1,162 +1,114 @@
1
- from dandy.llm import BaseLlmBot, LlmConfigOptions, Prompt
1
+ from __future__ import annotations
2
2
 
3
- from django_spire.ai.prompt.tuning import prompts, intel
3
+ from dandy import Bot, LlmConfigOptions, Prompt
4
4
 
5
+ from django_spire.ai.prompt.tuning import prompts, intel
5
6
 
6
7
 
7
- class PromptTestingBot(BaseLlmBot):
8
- instructions_prompt = Prompt()
9
- intel_class = intel.PromptTestingIntel
10
- config_options = LlmConfigOptions(temperature=0.4)
8
+ class PromptTestingBot(Bot):
9
+ llm_role = Prompt()
10
+ llm_config_options = LlmConfigOptions(temperature=0.4)
11
11
 
12
- @classmethod
13
12
  def process(
14
- cls,
15
- system_prompt: str,
16
- user_prompt: str,
17
-
18
- ) -> intel.PromptTuningIntel:
19
- """
20
- Takes a system prompt and a user prompt.
21
- Used to test the response of the system prompt.
22
- """
23
-
24
- cls.instructions_prompt = system_prompt
25
- return cls.process_prompt_to_intel(
26
- prompt=user_prompt
13
+ self,
14
+ system_prompt: str,
15
+ user_prompt: str
16
+ ) -> intel.PromptTestingIntel:
17
+ self.llm_role = system_prompt
18
+ return self.llm.prompt_to_intel(
19
+ prompt=user_prompt,
20
+ intel_class=intel.PromptTestingIntel
27
21
  )
28
22
 
29
23
 
30
- class SimplePromptTuningBot(BaseLlmBot):
31
- instructions_prompt = prompts.prompt_tuning_instruction_bot_prompt()
32
- intel_class = intel.PromptTuningIntel
33
- config_options = LlmConfigOptions(temperature=0.1)
24
+ class SimplePromptTuningBot(Bot):
25
+ llm_role = prompts.prompt_tuning_instruction_bot_prompt()
26
+ llm_config_options = LlmConfigOptions(temperature=0.1)
34
27
 
35
-
36
- @classmethod
37
28
  def process(
38
- cls,
39
- prompt: str,
40
- feedback: str,
41
-
29
+ self,
30
+ prompt: str,
31
+ feedback: str
42
32
  ) -> intel.PromptTuningIntel:
43
-
44
- return cls.process_prompt_to_intel(
33
+ return self.llm.prompt_to_intel(
45
34
  prompt=prompts.prompt_tuning_input_prompt(prompt, feedback),
35
+ intel_class=intel.PromptTuningIntel
46
36
  )
47
37
 
48
38
 
49
- class AdvancedPromptTuningBot(BaseLlmBot):
50
- instructions_prompt = prompts.prompt_tuning_instruction_bot_prompt()
51
- intel_class = intel.PromptTuningIntel
39
+ class AdvancedPromptTuningBot(Bot):
40
+ llm_role = prompts.prompt_tuning_instruction_bot_prompt()
52
41
 
53
- @classmethod
54
42
  def process(
55
- cls,
56
- system_prompt: str,
57
- feedback: str,
58
-
59
- ) -> intel.PromptTuningIntel:
60
- tuned_prompt = SimplePromptTuningBot.process(system_prompt, feedback)
61
- formatted_prompt = FormattingBot.process(tuned_prompt.prompt)
62
- remove_duplicates = DuplicationRemovalBot.process(formatted_prompt.prompt)
63
- improve_instructions = InstructionClarityBot.process(remove_duplicates.prompt)
64
- example_optimization = ExampleOptimizationBot.process(improve_instructions.prompt)
65
- persona = PersonaBot.process(example_optimization.prompt)
66
- return persona
67
-
68
-
69
- # return cls.process_prompt_to_intel(
70
- # prompt=prompts.prompt_tuning_input_prompt(system_prompt, feedback),
71
- # postfix_system_prompt=None
72
- # )
73
- #
74
-
75
- class FormattingBot(BaseLlmBot):
76
- """Bot that preserves structure and standardizes formatting of system prompts."""
77
- instructions_prompt = prompts.formatting_bot_instruction_prompt()
78
- intel_class = intel.PromptTuningIntel
79
-
80
- @classmethod
81
- def process(
82
- cls,
83
- system_prompt: str,
84
-
43
+ self,
44
+ system_prompt: str,
45
+ feedback: str
85
46
  ) -> intel.PromptTuningIntel:
86
-
87
- return cls.process_prompt_to_intel(
47
+ simple_bot = SimplePromptTuningBot()
48
+ formatting_bot = FormattingBot()
49
+ duplication_bot = DuplicationRemovalBot()
50
+ instruction_bot = InstructionClarityBot()
51
+ example_bot = ExampleOptimizationBot()
52
+ persona_bot = PersonaBot()
53
+
54
+ tuned_prompt = simple_bot.process(system_prompt, feedback)
55
+ formatted_prompt = formatting_bot.process(tuned_prompt.prompt)
56
+ remove_duplicates = duplication_bot.process(formatted_prompt.prompt)
57
+ improve_instructions = instruction_bot.process(remove_duplicates.prompt)
58
+ example_optimization = example_bot.process(improve_instructions.prompt)
59
+ return persona_bot.process(example_optimization.prompt)
60
+
61
+
62
+ class FormattingBot(Bot):
63
+ llm_role = prompts.formatting_bot_instruction_prompt()
64
+
65
+ def process(self, system_prompt: str) -> intel.PromptTuningIntel:
66
+ return self.llm.prompt_to_intel(
88
67
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
68
+ intel_class=intel.PromptTuningIntel,
89
69
  postfix_system_prompt=None
90
70
  )
91
71
 
92
72
 
93
- class InstructionClarityBot(BaseLlmBot):
94
- """Bot that focuses on improving the clarity of instructions in system prompts."""
95
- instructions_prompt = prompts.instruction_clarity_bot_instruction_prompt()
96
- intel_class = intel.PromptTuningIntel
97
-
98
- @classmethod
99
- def process(
100
- cls,
101
- system_prompt: str,
102
-
103
- ) -> intel.PromptTuningIntel:
73
+ class InstructionClarityBot(Bot):
74
+ llm_role = prompts.instruction_clarity_bot_instruction_prompt()
104
75
 
105
- return cls.process_prompt_to_intel(
76
+ def process(self, system_prompt: str) -> intel.PromptTuningIntel:
77
+ return self.llm.prompt_to_intel(
106
78
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
79
+ intel_class=intel.PromptTuningIntel,
107
80
  postfix_system_prompt=None
108
81
  )
109
82
 
110
83
 
111
- class PersonaBot(BaseLlmBot):
112
- """Bot that maintains consistent tone and persona throughout system prompts."""
113
- instructions_prompt = prompts.persona_bot_instruction_prompt()
114
- intel_class = intel.PromptTuningIntel
115
-
116
- @classmethod
117
- def process(
118
- cls,
119
- system_prompt: str,
84
+ class PersonaBot(Bot):
85
+ llm_role = prompts.persona_bot_instruction_prompt()
120
86
 
121
- ) -> intel.PromptTuningIntel:
122
-
123
- return cls.process_prompt_to_intel(
87
+ def process(self, system_prompt: str) -> intel.PromptTuningIntel:
88
+ return self.llm.prompt_to_intel(
124
89
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
90
+ intel_class=intel.PromptTuningIntel,
125
91
  postfix_system_prompt=None
126
92
  )
127
93
 
128
94
 
129
- class DuplicationRemovalBot(BaseLlmBot):
130
- """Bot that identifies and removes redundancies in system prompts."""
131
- instructions_prompt = prompts.duplication_removal_bot_instruction_prompt()
132
- intel_class = intel.PromptTuningIntel
133
-
134
- @classmethod
135
- def process(
136
- cls,
137
- system_prompt: str,
138
-
139
- ) -> intel.PromptTuningIntel:
95
+ class DuplicationRemovalBot(Bot):
96
+ llm_role = prompts.duplication_removal_bot_instruction_prompt()
140
97
 
141
- return cls.process_prompt_to_intel(
98
+ def process(self, system_prompt: str) -> intel.PromptTuningIntel:
99
+ return self.llm.prompt_to_intel(
142
100
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
101
+ intel_class=intel.PromptTuningIntel,
143
102
  postfix_system_prompt=None
144
103
  )
145
104
 
146
105
 
147
- class ExampleOptimizationBot(BaseLlmBot):
148
- """Bot that refines examples within system prompts."""
149
- instructions_prompt = prompts.example_optimization_bot_instruction_prompt()
150
- intel_class = intel.PromptTuningIntel
151
-
152
- @classmethod
153
- def process(
154
- cls,
155
- system_prompt: str,
156
-
157
- ) -> intel.PromptTuningIntel:
106
+ class ExampleOptimizationBot(Bot):
107
+ llm_role = prompts.example_optimization_bot_instruction_prompt()
158
108
 
159
- return cls.process_prompt_to_intel(
109
+ def process(self, system_prompt: str) -> intel.PromptTuningIntel:
110
+ return self.llm.prompt_to_intel(
160
111
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
112
+ intel_class=intel.PromptTuningIntel,
161
113
  postfix_system_prompt=None
162
114
  )
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dandy.intel import BaseIntel
3
+ from dandy import BaseIntel
4
4
 
5
5
 
6
6
  class PromptTestingIntel(BaseIntel):
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.db import models
2
4
  from django.contrib.postgres.fields import JSONField
3
5
 
@@ -1,4 +1,6 @@
1
- from dandy.recorder import Recorder
1
+ from __future__ import annotations
2
+
3
+ from dandy import Recorder
2
4
 
3
5
  from django_spire.ai.prompt.bots import DandyPythonPromptBot
4
6
  from django_spire.ai.prompt.tuning.bots import SimplePromptTuningBot
@@ -7,8 +9,8 @@ from django_spire.ai.prompt.tuning.bots import SimplePromptTuningBot
7
9
  def prompt_tuning_cli(prompt: str):
8
10
  Recorder.start_recording(recording_name='prompt_tuning')
9
11
 
10
- # ENTER YOUR PROMPT HERE!
11
12
  holding = prompt
13
+ tuning_bot = SimplePromptTuningBot()
12
14
 
13
15
  print('----------------------------------------------------')
14
16
 
@@ -21,10 +23,7 @@ def prompt_tuning_cli(prompt: str):
21
23
 
22
24
  print('Attempting to tune prompt.....')
23
25
 
24
- new_prompt = (
25
- SimplePromptTuningBot()
26
- .process(holding, feedback)
27
- )
26
+ new_prompt = tuning_bot.process(holding, feedback)
28
27
  holding = new_prompt.prompt
29
28
 
30
29
  print('----------------------NEW PROMPT START------------------------------')
@@ -34,7 +33,8 @@ def prompt_tuning_cli(prompt: str):
34
33
  print('----------------------NEW PROMPT END------------------------------')
35
34
  print()
36
35
 
37
-
38
36
  Recorder.stop_recording(recording_name='prompt_tuning')
39
37
  Recorder.to_html_file(recording_name='prompt_tuning')
40
- DandyPythonPromptBot().process(prompt)
38
+
39
+ python_bot = DandyPythonPromptBot()
40
+ python_bot.process(prompt)
@@ -1,4 +1,6 @@
1
- from dandy.llm import Prompt
1
+ from __future__ import annotations
2
+
3
+ from dandy import Prompt
2
4
 
3
5
 
4
6
  def prompt_tuning_instruction_bot_prompt():
@@ -181,7 +183,7 @@ def example_optimization_bot_instruction_prompt():
181
183
  )
182
184
 
183
185
 
184
- def prompt_tuning_input_prompt(system_prompt: str, feedback:str):
186
+ def prompt_tuning_input_prompt(system_prompt: str, feedback: str):
185
187
  return (
186
188
  Prompt()
187
189
  .heading('User Supplies System Prompt')
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from urllib.parse import urlencode
2
4
 
3
5
  from django.contrib import admin
@@ -45,4 +47,4 @@ class SmsMessageAdmin(admin.ModelAdmin):
45
47
  readonly_fields = ('created_datetime', )
46
48
 
47
49
  class Meta:
48
- ordering = ('created_datetime', )
50
+ ordering = ('created_datetime', )
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.apps import AppConfig
2
4
  from django.conf import settings
3
5
 
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import functools
2
4
  import os
3
5
 
@@ -1,5 +1,7 @@
1
- from dandy.intel import BaseIntel
1
+ from __future__ import annotations
2
+
3
+ from dandy import BaseIntel
2
4
 
3
5
 
4
6
  class SmsIntel(BaseIntel):
5
- body: str
7
+ body: str
@@ -1,20 +1,20 @@
1
+ from __future__ import annotations
2
+
1
3
  from dandy.recorder import recorder_to_html_file
2
- from dandy.workflow import BaseWorkflow
3
- from dandy.llm import MessageHistory
4
+ from dandy.llm.request.message import MessageHistory
4
5
  from django.core.handlers.wsgi import WSGIRequest
5
6
 
6
7
  from django_spire.ai.chat.intelligence.workflows.chat_workflow import SpireChatWorkflow
7
8
  from django_spire.ai.sms.intel import SmsIntel
8
9
 
9
10
 
10
- class SpireSmsConversationWorkflow(BaseWorkflow):
11
- @classmethod
11
+ class SpireSmsConversationWorkflow:
12
+ @staticmethod
12
13
  @recorder_to_html_file('sms_workflow')
13
14
  def process(
14
- cls,
15
- request: WSGIRequest,
16
- user_input: str,
17
- message_history: MessageHistory | None = None
15
+ request: WSGIRequest,
16
+ user_input: str,
17
+ message_history: MessageHistory | None = None
18
18
  ) -> SmsIntel:
19
19
  return SmsIntel(
20
20
  body=str(
@@ -1,5 +1,6 @@
1
- from dandy.llm import MessageHistory
2
- from dandy.llm.service.request.message import RoleLiteralStr
1
+ from __future__ import annotations
2
+
3
+ from dandy.llm.request.message import MessageHistory, RoleLiteralStr
3
4
  from django.contrib.auth.models import User
4
5
  from django.db import models
5
6
  from django.utils.timezone import now
@@ -27,11 +28,11 @@ class SmsConversation(HistoryModelMixin):
27
28
  return f"SMS Conversation with {self.phone_number}"
28
29
 
29
30
  def add_message(
30
- self,
31
- body: str,
32
- is_inbound: bool,
33
- twilio_sid: str,
34
- is_processed: bool = False,
31
+ self,
32
+ body: str,
33
+ is_inbound: bool,
34
+ twilio_sid: str,
35
+ is_processed: bool = False
35
36
  ):
36
37
  message = self.messages.create(
37
38
  body=body,
@@ -46,9 +47,9 @@ class SmsConversation(HistoryModelMixin):
46
47
  return message
47
48
 
48
49
  def generate_message_history(
49
- self,
50
- message_count: int = 20,
51
- exclude_last_message: bool = True
50
+ self,
51
+ message_count: int = 20,
52
+ exclude_last_message: bool = True
52
53
  ) -> MessageHistory:
53
54
  message_history = MessageHistory()
54
55
 
@@ -114,13 +115,14 @@ class SmsMessage(HistoryModelMixin):
114
115
  def role(self) -> RoleLiteralStr:
115
116
  if self.is_inbound:
116
117
  return 'user'
117
- elif self.is_outbound:
118
+
119
+ if self.is_outbound:
118
120
  return 'assistant'
119
- else:
120
- return 'system'
121
+
122
+ return 'system'
121
123
 
122
124
  class Meta:
123
125
  db_table = 'django_spire_ai_sms_message'
124
126
  verbose_name = 'SMS Message'
125
127
  verbose_name_plural = 'SMS Messages'
126
- ordering = ('-created_datetime',)
128
+ ordering = ('-created_datetime',)
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django_spire.history.querysets import HistoryQuerySet
2
4
 
3
5
 
@@ -7,9 +9,10 @@ class SmsConversationQuerySet(HistoryQuerySet):
7
9
  phone_number=phone_number,
8
10
  )
9
11
 
12
+
10
13
  class SmsMessageQuerySet(HistoryQuerySet):
11
14
  def newest_by_count(self, count: int = 20):
12
15
  return self.order_by('-created_datetime')[:count]
13
16
 
14
17
  def newest_by_count_reversed(self, count: int = 20):
15
- return self.order_by('-created_datetime')[:count][::-1]
18
+ return self.order_by('-created_datetime')[:count][::-1]
@@ -1,7 +1,8 @@
1
+ from __future__ import annotations
2
+
1
3
  from importlib import import_module
2
4
 
3
- from dandy.llm import MessageHistory
4
- from dandy.workflow import BaseWorkflow
5
+ from dandy.llm.request.message import MessageHistory
5
6
  from django.conf import settings
6
7
  from django.contrib.auth.base_user import AbstractBaseUser
7
8
  from django.core.handlers.wsgi import WSGIRequest
@@ -12,20 +13,21 @@ from django_spire.consts import AI_SMS_CONVERSATION_WORKFLOW_CLASS_SETTINGS_NAME
12
13
 
13
14
 
14
15
  def sms_workflow_process(
15
- request: WSGIRequest,
16
- user_input: str | None = None,
17
- message_history: MessageHistory | None = None,
18
- user: AbstractBaseUser | None = None,
19
- actor: str | None = None,
16
+ request: WSGIRequest,
17
+ user_input: str | None = None,
18
+ message_history: MessageHistory | None = None,
19
+ user: AbstractBaseUser | None = None,
20
+ actor: str | None = None
20
21
  ) -> SmsIntel:
21
-
22
22
  if user_input is None:
23
- raise ValueError('sms user_input is required')
23
+ message = 'SMS user_input is required'
24
+ raise ValueError(message)
24
25
 
25
26
  sms_workflow_class = getattr(settings, AI_SMS_CONVERSATION_WORKFLOW_CLASS_SETTINGS_NAME)
26
-
27
+
27
28
  if sms_workflow_class is None:
28
- raise ValueError(f'"{AI_SMS_CONVERSATION_WORKFLOW_CLASS_SETTINGS_NAME}" must be set in the django settings.')
29
+ message = f'"{AI_SMS_CONVERSATION_WORKFLOW_CLASS_SETTINGS_NAME}" must be set in the django settings.'
30
+ raise ValueError(message)
29
31
 
30
32
  module_name = '.'.join(sms_workflow_class.split('.')[:-1])
31
33
  object_name = sms_workflow_class.split('.')[-1]
@@ -33,9 +35,10 @@ def sms_workflow_process(
33
35
  try:
34
36
  workflow_module = import_module(module_name)
35
37
  except ImportError:
36
- raise ImportError(f'Could not import workflow module: {module_name}')
38
+ message = f'Could not import workflow module: {module_name}'
39
+ raise ImportError(message) from None
37
40
 
38
- SmsWorkFlow: BaseWorkflow = getattr(workflow_module, object_name)
41
+ SmsWorkFlow = getattr(workflow_module, object_name)
39
42
 
40
43
  @log_ai_interaction_from_recorder(user=user, actor=actor)
41
44
  def run_workflow_process() -> SmsIntel:
@@ -48,8 +51,7 @@ def sms_workflow_process(
48
51
  output_intel = run_workflow_process()
49
52
 
50
53
  if not issubclass(output_intel.__class__, SmsIntel):
51
- raise ValueError(
52
- f'{SmsWorkFlow.__class__.__module__}.{SmsWorkFlow.__class__.__qualname__}.process must return an instance of a {SmsIntel.__name__}.'
53
- )
54
+ message = f'{SmsWorkFlow.__class__.__module__}.{SmsWorkFlow.__class__.__qualname__}.process must return an instance of a {SmsIntel.__name__}.'
55
+ raise TypeError(message)
54
56
 
55
57
  return output_intel
@@ -6,4 +6,4 @@ app_name = 'sms'
6
6
 
7
7
  urlpatterns = [
8
8
  path('webhook/', views.webhook_view, name='webhook'),
9
- ]
9
+ ]
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.http import HttpResponse, HttpResponseForbidden
2
4
  from django.views.decorators.csrf import csrf_exempt
3
5
  from django.views.decorators.http import require_POST
@@ -1,8 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dandy.intel import BaseIntel
4
- from dandy.llm import LlmBot
5
- from dandy.recorder import recorder_to_html_file
3
+ from dandy import BaseIntel, Bot, recorder_to_html_file
6
4
 
7
5
  from django_spire.ai.decorators import log_ai_interaction_from_recorder
8
6
  from django_spire.core.tests.test_cases import BaseTestCase
@@ -19,8 +17,8 @@ class AiTestCase(BaseTestCase):
19
17
  @log_ai_interaction_from_recorder(self.super_user, 'horse')
20
18
  @recorder_to_html_file('horse')
21
19
  def generate_horse_intel(user_input: str) -> HorseIntel:
22
-
23
- return LlmBot.process(
20
+ bot = Bot()
21
+ return bot.llm.prompt_to_intel(
24
22
  prompt=user_input,
25
23
  intel_class=HorseIntel,
26
24
  )
django_spire/ai/urls.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from django.urls import include, path
2
2
 
3
+
3
4
  app_name = 'ai'
4
5
 
5
6
  urlpatterns = [
django_spire/consts.py CHANGED
@@ -1,4 +1,4 @@
1
- __VERSION__ = '0.16.11'
1
+ __VERSION__ = '0.16.13'
2
2
 
3
3
 
4
4
  AI_CHAT_WORKFLOW_SENDER_SETTINGS_NAME = 'AI_CHAT_WORKFLOW_NAME'
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dandy.llm import Prompt
4
- from dandy.intel import BaseIntel
3
+ from dandy import BaseIntel, Prompt
5
4
 
6
5
  from django_spire.core.converters import django_to_pydantic_model, fake_model_field_value
7
6
  from django_spire.contrib.seeding.field.base import BaseFieldSeeder
@@ -40,6 +39,9 @@ class DjangoFieldLlmSeeder(BaseFieldSeeder):
40
39
  .prompt(self.field_prompt)
41
40
  )
42
41
 
42
+ # Instantiate the bot once
43
+ bot = LlmFieldSeedingBot()
44
+
43
45
  if count <= 25:
44
46
  # Create a prompt for the full count since it's within a single batch
45
47
  prompt = (
@@ -49,7 +51,7 @@ class DjangoFieldLlmSeeder(BaseFieldSeeder):
49
51
  .prompt(base_prompt)
50
52
  )
51
53
 
52
- intel_data = LlmFieldSeedingBot.process(
54
+ intel_data = bot.process(
53
55
  prompt=prompt,
54
56
  intel_class=SeedingIntel
55
57
  )
@@ -73,7 +75,7 @@ class DjangoFieldLlmSeeder(BaseFieldSeeder):
73
75
  .prompt(base_prompt)
74
76
  )
75
77
 
76
- future = LlmFieldSeedingBot.process_to_future(
78
+ future = bot.process_to_future(
77
79
  prompt=batch_prompt,
78
80
  intel_class=SeedingIntel
79
81
  )
@@ -1,8 +1,7 @@
1
1
  # from django_spire.seeding.intelligence.bots import LlmSeedingBot
2
2
  # from django_spire.seeding.seeder import BaseSeeder
3
3
  #
4
- # from dandy.llm import Prompt
5
- # from dandy.intel import BaseIntel
4
+ # from dandy import BaseIntel, Prompt
6
5
  #
7
6
  #
8
7
  # class LlmSeeder(BaseSeeder):
@@ -2,18 +2,18 @@ from __future__ import annotations
2
2
 
3
3
  from django.utils.timezone import localdate
4
4
 
5
- from dandy.llm import LlmBot, LlmConfigOptions, Prompt
5
+ from dandy import Bot, LlmConfigOptions, Prompt
6
6
 
7
7
 
8
- class LlmFieldSeedingBot(LlmBot):
9
- config = 'SEEDING_LLM_BOT'
8
+ class LlmFieldSeedingBot(Bot):
9
+ llm_config = 'SEEDING_LLM_BOT'
10
10
 
11
- config_options = LlmConfigOptions(
11
+ llm_config_options = LlmConfigOptions(
12
12
  randomize_seed=True,
13
13
  temperature=0.5
14
14
  )
15
15
 
16
- instructions_prompt = (
16
+ llm_role = (
17
17
  Prompt()
18
18
  .title('You are a database seeding bot.')
19
19
  .text('Below you will find rules and instructions.')
@@ -23,9 +23,8 @@ class LlmFieldSeedingBot(LlmBot):
23
23
  .text(f'Today\'s date is {localdate().strftime("%Y-%m-%d")} use this in context for generating dates and datetimes')
24
24
  )
25
25
 
26
- @classmethod
27
- def process(cls, prompt: Prompt, intel_class) -> list[dict]:
28
- intel_data = cls.process_prompt_to_intel(
26
+ def process(self, prompt: Prompt, intel_class) -> list[dict]:
27
+ intel_data = self.llm.prompt_to_intel(
29
28
  prompt=prompt,
30
29
  intel_class=intel_class
31
30
  )