django-cfg 1.1.82__py3-none-any.whl → 1.2.1__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 (244) hide show
  1. django_cfg/__init__.py +20 -448
  2. django_cfg/apps/accounts/README.md +3 -3
  3. django_cfg/apps/accounts/admin/__init__.py +0 -2
  4. django_cfg/apps/accounts/admin/activity.py +2 -9
  5. django_cfg/apps/accounts/admin/filters.py +0 -42
  6. django_cfg/apps/accounts/admin/inlines.py +8 -8
  7. django_cfg/apps/accounts/admin/otp.py +5 -5
  8. django_cfg/apps/accounts/admin/registration_source.py +1 -8
  9. django_cfg/apps/accounts/admin/user.py +12 -20
  10. django_cfg/apps/accounts/managers/user_manager.py +2 -129
  11. django_cfg/apps/accounts/migrations/0006_remove_twilioresponse_otp_secret_and_more.py +46 -0
  12. django_cfg/apps/accounts/models.py +3 -123
  13. django_cfg/apps/accounts/serializers/otp.py +40 -44
  14. django_cfg/apps/accounts/serializers/profile.py +0 -2
  15. django_cfg/apps/accounts/services/otp_service.py +98 -186
  16. django_cfg/apps/accounts/signals.py +25 -15
  17. django_cfg/apps/accounts/utils/auth_email_service.py +84 -0
  18. django_cfg/apps/accounts/views/otp.py +35 -36
  19. django_cfg/apps/agents/README.md +129 -0
  20. django_cfg/apps/agents/__init__.py +68 -0
  21. django_cfg/apps/agents/admin/__init__.py +17 -0
  22. django_cfg/apps/agents/admin/execution_admin.py +460 -0
  23. django_cfg/apps/agents/admin/registry_admin.py +360 -0
  24. django_cfg/apps/agents/admin/toolsets_admin.py +482 -0
  25. django_cfg/apps/agents/apps.py +29 -0
  26. django_cfg/apps/agents/core/__init__.py +20 -0
  27. django_cfg/apps/agents/core/agent.py +281 -0
  28. django_cfg/apps/agents/core/dependencies.py +154 -0
  29. django_cfg/apps/agents/core/exceptions.py +66 -0
  30. django_cfg/apps/agents/core/models.py +106 -0
  31. django_cfg/apps/agents/core/orchestrator.py +391 -0
  32. django_cfg/apps/agents/examples/__init__.py +3 -0
  33. django_cfg/apps/agents/examples/simple_example.py +161 -0
  34. django_cfg/apps/agents/integration/__init__.py +14 -0
  35. django_cfg/apps/agents/integration/middleware.py +80 -0
  36. django_cfg/apps/agents/integration/registry.py +345 -0
  37. django_cfg/apps/agents/integration/signals.py +50 -0
  38. django_cfg/apps/agents/management/__init__.py +3 -0
  39. django_cfg/apps/agents/management/commands/__init__.py +3 -0
  40. django_cfg/apps/agents/management/commands/create_agent.py +365 -0
  41. django_cfg/apps/agents/management/commands/orchestrator_status.py +191 -0
  42. django_cfg/apps/agents/managers/__init__.py +23 -0
  43. django_cfg/apps/agents/managers/execution.py +236 -0
  44. django_cfg/apps/agents/managers/registry.py +254 -0
  45. django_cfg/apps/agents/managers/toolsets.py +496 -0
  46. django_cfg/apps/agents/migrations/0001_initial.py +286 -0
  47. django_cfg/apps/agents/migrations/__init__.py +5 -0
  48. django_cfg/apps/agents/models/__init__.py +15 -0
  49. django_cfg/apps/agents/models/execution.py +215 -0
  50. django_cfg/apps/agents/models/registry.py +220 -0
  51. django_cfg/apps/agents/models/toolsets.py +305 -0
  52. django_cfg/apps/agents/patterns/__init__.py +24 -0
  53. django_cfg/apps/agents/patterns/content_agents.py +234 -0
  54. django_cfg/apps/agents/toolsets/__init__.py +15 -0
  55. django_cfg/apps/agents/toolsets/cache_toolset.py +285 -0
  56. django_cfg/apps/agents/toolsets/django_toolset.py +220 -0
  57. django_cfg/apps/agents/toolsets/file_toolset.py +324 -0
  58. django_cfg/apps/agents/toolsets/orm_toolset.py +319 -0
  59. django_cfg/apps/agents/urls.py +46 -0
  60. django_cfg/apps/knowbase/README.md +150 -0
  61. django_cfg/apps/knowbase/__init__.py +27 -0
  62. django_cfg/apps/knowbase/admin/__init__.py +23 -0
  63. django_cfg/apps/knowbase/admin/archive_admin.py +857 -0
  64. django_cfg/apps/knowbase/admin/chat_admin.py +386 -0
  65. django_cfg/apps/knowbase/admin/document_admin.py +650 -0
  66. django_cfg/apps/knowbase/admin/external_data_admin.py +685 -0
  67. django_cfg/apps/knowbase/apps.py +81 -0
  68. django_cfg/apps/knowbase/config/README.md +176 -0
  69. django_cfg/apps/knowbase/config/__init__.py +51 -0
  70. django_cfg/apps/knowbase/config/constance_fields.py +186 -0
  71. django_cfg/apps/knowbase/config/constance_settings.py +200 -0
  72. django_cfg/apps/knowbase/config/settings.py +450 -0
  73. django_cfg/apps/knowbase/examples/__init__.py +3 -0
  74. django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
  75. django_cfg/apps/knowbase/management/__init__.py +0 -0
  76. django_cfg/apps/knowbase/management/commands/__init__.py +0 -0
  77. django_cfg/apps/knowbase/management/commands/knowbase_stats.py +158 -0
  78. django_cfg/apps/knowbase/management/commands/setup_knowbase.py +59 -0
  79. django_cfg/apps/knowbase/managers/__init__.py +22 -0
  80. django_cfg/apps/knowbase/managers/archive.py +426 -0
  81. django_cfg/apps/knowbase/managers/base.py +32 -0
  82. django_cfg/apps/knowbase/managers/chat.py +141 -0
  83. django_cfg/apps/knowbase/managers/document.py +203 -0
  84. django_cfg/apps/knowbase/managers/external_data.py +471 -0
  85. django_cfg/apps/knowbase/migrations/0001_initial.py +427 -0
  86. django_cfg/apps/knowbase/migrations/0002_archiveitem_archiveitemchunk_documentarchive_and_more.py +434 -0
  87. django_cfg/apps/knowbase/migrations/__init__.py +5 -0
  88. django_cfg/apps/knowbase/mixins/__init__.py +15 -0
  89. django_cfg/apps/knowbase/mixins/config.py +108 -0
  90. django_cfg/apps/knowbase/mixins/creator.py +81 -0
  91. django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +199 -0
  92. django_cfg/apps/knowbase/mixins/external_data_mixin.py +813 -0
  93. django_cfg/apps/knowbase/mixins/service.py +362 -0
  94. django_cfg/apps/knowbase/models/__init__.py +41 -0
  95. django_cfg/apps/knowbase/models/archive.py +599 -0
  96. django_cfg/apps/knowbase/models/base.py +58 -0
  97. django_cfg/apps/knowbase/models/chat.py +157 -0
  98. django_cfg/apps/knowbase/models/document.py +267 -0
  99. django_cfg/apps/knowbase/models/external_data.py +376 -0
  100. django_cfg/apps/knowbase/serializers/__init__.py +68 -0
  101. django_cfg/apps/knowbase/serializers/archive_serializers.py +386 -0
  102. django_cfg/apps/knowbase/serializers/chat_serializers.py +137 -0
  103. django_cfg/apps/knowbase/serializers/document_serializers.py +94 -0
  104. django_cfg/apps/knowbase/serializers/external_data_serializers.py +256 -0
  105. django_cfg/apps/knowbase/serializers/public_serializers.py +74 -0
  106. django_cfg/apps/knowbase/services/__init__.py +40 -0
  107. django_cfg/apps/knowbase/services/archive/__init__.py +42 -0
  108. django_cfg/apps/knowbase/services/archive/archive_service.py +541 -0
  109. django_cfg/apps/knowbase/services/archive/chunking_service.py +791 -0
  110. django_cfg/apps/knowbase/services/archive/exceptions.py +52 -0
  111. django_cfg/apps/knowbase/services/archive/extraction_service.py +508 -0
  112. django_cfg/apps/knowbase/services/archive/vectorization_service.py +362 -0
  113. django_cfg/apps/knowbase/services/base.py +53 -0
  114. django_cfg/apps/knowbase/services/chat_service.py +239 -0
  115. django_cfg/apps/knowbase/services/document_service.py +144 -0
  116. django_cfg/apps/knowbase/services/embedding/__init__.py +43 -0
  117. django_cfg/apps/knowbase/services/embedding/async_processor.py +244 -0
  118. django_cfg/apps/knowbase/services/embedding/batch_processor.py +250 -0
  119. django_cfg/apps/knowbase/services/embedding/batch_result.py +61 -0
  120. django_cfg/apps/knowbase/services/embedding/models.py +229 -0
  121. django_cfg/apps/knowbase/services/embedding/processors.py +148 -0
  122. django_cfg/apps/knowbase/services/embedding/utils.py +176 -0
  123. django_cfg/apps/knowbase/services/prompt_builder.py +191 -0
  124. django_cfg/apps/knowbase/services/search_service.py +293 -0
  125. django_cfg/apps/knowbase/signals/__init__.py +21 -0
  126. django_cfg/apps/knowbase/signals/archive_signals.py +211 -0
  127. django_cfg/apps/knowbase/signals/chat_signals.py +37 -0
  128. django_cfg/apps/knowbase/signals/document_signals.py +143 -0
  129. django_cfg/apps/knowbase/signals/external_data_signals.py +157 -0
  130. django_cfg/apps/knowbase/tasks/__init__.py +39 -0
  131. django_cfg/apps/knowbase/tasks/archive_tasks.py +316 -0
  132. django_cfg/apps/knowbase/tasks/document_processing.py +341 -0
  133. django_cfg/apps/knowbase/tasks/external_data_tasks.py +341 -0
  134. django_cfg/apps/knowbase/tasks/maintenance.py +195 -0
  135. django_cfg/apps/knowbase/urls.py +43 -0
  136. django_cfg/apps/knowbase/utils/__init__.py +12 -0
  137. django_cfg/apps/knowbase/utils/chunk_settings.py +261 -0
  138. django_cfg/apps/knowbase/utils/text_processing.py +375 -0
  139. django_cfg/apps/knowbase/utils/validation.py +99 -0
  140. django_cfg/apps/knowbase/views/__init__.py +28 -0
  141. django_cfg/apps/knowbase/views/archive_views.py +469 -0
  142. django_cfg/apps/knowbase/views/base.py +49 -0
  143. django_cfg/apps/knowbase/views/chat_views.py +181 -0
  144. django_cfg/apps/knowbase/views/document_views.py +183 -0
  145. django_cfg/apps/knowbase/views/public_views.py +129 -0
  146. django_cfg/apps/leads/admin.py +70 -0
  147. django_cfg/apps/newsletter/admin.py +234 -0
  148. django_cfg/apps/newsletter/admin_filters.py +124 -0
  149. django_cfg/apps/support/admin.py +196 -0
  150. django_cfg/apps/support/admin_filters.py +71 -0
  151. django_cfg/apps/support/templates/support/chat/ticket_chat.html +1 -1
  152. django_cfg/apps/urls.py +5 -4
  153. django_cfg/cli/README.md +1 -1
  154. django_cfg/cli/commands/create_project.py +2 -2
  155. django_cfg/cli/commands/info.py +1 -1
  156. django_cfg/config.py +44 -0
  157. django_cfg/core/config.py +29 -82
  158. django_cfg/core/environment.py +1 -1
  159. django_cfg/core/generation.py +19 -107
  160. django_cfg/{integration.py → core/integration.py} +18 -16
  161. django_cfg/core/validation.py +1 -1
  162. django_cfg/management/__init__.py +1 -1
  163. django_cfg/management/commands/__init__.py +1 -1
  164. django_cfg/management/commands/auto_generate.py +482 -0
  165. django_cfg/management/commands/migrator.py +19 -101
  166. django_cfg/management/commands/test_email.py +1 -1
  167. django_cfg/middleware/README.md +0 -158
  168. django_cfg/middleware/__init__.py +0 -2
  169. django_cfg/middleware/user_activity.py +3 -3
  170. django_cfg/models/api.py +145 -0
  171. django_cfg/models/base.py +287 -0
  172. django_cfg/models/cache.py +4 -4
  173. django_cfg/models/constance.py +25 -88
  174. django_cfg/models/database.py +9 -9
  175. django_cfg/models/drf.py +3 -36
  176. django_cfg/models/email.py +163 -0
  177. django_cfg/models/environment.py +276 -0
  178. django_cfg/models/limits.py +1 -1
  179. django_cfg/models/logging.py +366 -0
  180. django_cfg/models/revolution.py +41 -2
  181. django_cfg/models/security.py +125 -0
  182. django_cfg/models/services.py +1 -1
  183. django_cfg/modules/__init__.py +2 -56
  184. django_cfg/modules/base.py +78 -52
  185. django_cfg/modules/django_currency/service.py +2 -2
  186. django_cfg/modules/django_email.py +2 -2
  187. django_cfg/modules/django_health.py +267 -0
  188. django_cfg/modules/django_llm/llm/client.py +91 -19
  189. django_cfg/modules/django_llm/translator/translator.py +2 -2
  190. django_cfg/modules/django_logger.py +2 -2
  191. django_cfg/modules/django_ngrok.py +2 -2
  192. django_cfg/modules/django_tasks.py +68 -3
  193. django_cfg/modules/django_telegram.py +3 -3
  194. django_cfg/modules/django_twilio/sendgrid_service.py +2 -2
  195. django_cfg/modules/django_twilio/service.py +2 -2
  196. django_cfg/modules/django_twilio/simple_service.py +2 -2
  197. django_cfg/modules/django_twilio/twilio_service.py +2 -2
  198. django_cfg/modules/django_unfold/__init__.py +69 -0
  199. django_cfg/modules/{unfold → django_unfold}/callbacks.py +23 -22
  200. django_cfg/modules/django_unfold/dashboard.py +278 -0
  201. django_cfg/modules/django_unfold/icons/README.md +145 -0
  202. django_cfg/modules/django_unfold/icons/__init__.py +12 -0
  203. django_cfg/modules/django_unfold/icons/constants.py +2851 -0
  204. django_cfg/modules/django_unfold/icons/generate_icons.py +486 -0
  205. django_cfg/modules/django_unfold/models/__init__.py +42 -0
  206. django_cfg/modules/django_unfold/models/config.py +601 -0
  207. django_cfg/modules/django_unfold/models/dashboard.py +206 -0
  208. django_cfg/modules/django_unfold/models/dropdown.py +40 -0
  209. django_cfg/modules/django_unfold/models/navigation.py +73 -0
  210. django_cfg/modules/django_unfold/models/tabs.py +25 -0
  211. django_cfg/modules/{unfold → django_unfold}/system_monitor.py +2 -2
  212. django_cfg/modules/django_unfold/utils.py +140 -0
  213. django_cfg/registry/__init__.py +23 -0
  214. django_cfg/registry/core.py +61 -0
  215. django_cfg/registry/exceptions.py +11 -0
  216. django_cfg/registry/modules.py +12 -0
  217. django_cfg/registry/services.py +26 -0
  218. django_cfg/registry/third_party.py +52 -0
  219. django_cfg/routing/__init__.py +19 -0
  220. django_cfg/routing/callbacks.py +198 -0
  221. django_cfg/routing/routers.py +48 -0
  222. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +8 -9
  223. django_cfg/templatetags/__init__.py +0 -0
  224. django_cfg/templatetags/django_cfg.py +33 -0
  225. django_cfg/urls.py +33 -0
  226. django_cfg/utils/path_resolution.py +1 -1
  227. django_cfg/utils/smart_defaults.py +7 -61
  228. django_cfg/utils/toolkit.py +663 -0
  229. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/METADATA +83 -86
  230. django_cfg-1.2.1.dist-info/RECORD +441 -0
  231. django_cfg/archive/django_sample.zip +0 -0
  232. django_cfg/models/unfold.py +0 -271
  233. django_cfg/modules/unfold/__init__.py +0 -29
  234. django_cfg/modules/unfold/dashboard.py +0 -318
  235. django_cfg/pyproject.toml +0 -370
  236. django_cfg/routers.py +0 -83
  237. django_cfg-1.1.82.dist-info/RECORD +0 -278
  238. /django_cfg/{exceptions.py → core/exceptions.py} +0 -0
  239. /django_cfg/modules/{unfold → django_unfold}/models.py +0 -0
  240. /django_cfg/modules/{unfold → django_unfold}/tailwind.py +0 -0
  241. /django_cfg/{version_check.py → utils/version_check.py} +0 -0
  242. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/WHEEL +0 -0
  243. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/entry_points.txt +0 -0
  244. {django_cfg-1.1.82.dist-info → django_cfg-1.2.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,319 @@
1
+ """
2
+ Django ORM toolset for database operations.
3
+ """
4
+
5
+ import logging
6
+ from typing import Dict, Any, List, Optional, Union
7
+ from pydantic_ai.toolsets import AbstractToolset
8
+ from pydantic_ai import RunContext
9
+ from django.db import models
10
+ from django.apps import apps
11
+
12
+ from ..core.dependencies import DjangoDeps
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class ORMToolset(AbstractToolset[DjangoDeps]):
18
+ """
19
+ Django ORM toolset for safe database operations.
20
+
21
+ Provides tools for:
22
+ - Model queries (read-only by default)
23
+ - Data aggregation
24
+ - Relationship traversal
25
+ - Safe filtering
26
+ """
27
+
28
+ def __init__(self, read_only: bool = True, allowed_models: Optional[List[str]] = None):
29
+ """
30
+ Initialize ORM toolset.
31
+
32
+ Args:
33
+ read_only: If True, only allow read operations
34
+ allowed_models: List of allowed models in format "app_label.model_name"
35
+ """
36
+ self.read_only = read_only
37
+ self.allowed_models = set(allowed_models) if allowed_models else None
38
+
39
+ @property
40
+ def id(self) -> str:
41
+ return "django_orm"
42
+
43
+ def _check_model_access(self, app_label: str, model_name: str) -> bool:
44
+ """Check if model access is allowed."""
45
+ if self.allowed_models is None:
46
+ return True
47
+
48
+ model_key = f"{app_label}.{model_name}"
49
+ return model_key in self.allowed_models
50
+
51
+ def _get_model(self, app_label: str, model_name: str) -> models.Model:
52
+ """Get Django model class with access check."""
53
+ if not self._check_model_access(app_label, model_name):
54
+ raise PermissionError(f"Access to model '{app_label}.{model_name}' not allowed")
55
+
56
+ try:
57
+ return apps.get_model(app_label, model_name)
58
+ except LookupError:
59
+ raise ValueError(f"Model '{app_label}.{model_name}' not found")
60
+
61
+ async def count_objects(
62
+ self,
63
+ ctx: RunContext[DjangoDeps],
64
+ app_label: str,
65
+ model_name: str,
66
+ filters: Optional[Dict[str, Any]] = None
67
+ ) -> int:
68
+ """Count objects in model with optional filters."""
69
+ model = self._get_model(app_label, model_name)
70
+
71
+ queryset = model.objects.all()
72
+
73
+ if filters:
74
+ # Apply safe filters
75
+ safe_filters = self._sanitize_filters(filters)
76
+ queryset = queryset.filter(**safe_filters)
77
+
78
+ return await queryset.acount()
79
+
80
+ async def get_object(
81
+ self,
82
+ ctx: RunContext[DjangoDeps],
83
+ app_label: str,
84
+ model_name: str,
85
+ object_id: Union[int, str]
86
+ ) -> Optional[Dict[str, Any]]:
87
+ """Get single object by ID."""
88
+ model = self._get_model(app_label, model_name)
89
+
90
+ try:
91
+ obj = await model.objects.aget(pk=object_id)
92
+ return self._serialize_object(obj)
93
+ except model.DoesNotExist:
94
+ return None
95
+
96
+ async def list_objects(
97
+ self,
98
+ ctx: RunContext[DjangoDeps],
99
+ app_label: str,
100
+ model_name: str,
101
+ filters: Optional[Dict[str, Any]] = None,
102
+ limit: int = 10,
103
+ offset: int = 0,
104
+ order_by: Optional[str] = None
105
+ ) -> Dict[str, Any]:
106
+ """List objects with pagination and filtering."""
107
+ model = self._get_model(app_label, model_name)
108
+
109
+ queryset = model.objects.all()
110
+
111
+ # Apply filters
112
+ if filters:
113
+ safe_filters = self._sanitize_filters(filters)
114
+ queryset = queryset.filter(**safe_filters)
115
+
116
+ # Apply ordering
117
+ if order_by:
118
+ # Sanitize order_by field
119
+ order_field = order_by.lstrip('-')
120
+ if hasattr(model, order_field):
121
+ queryset = queryset.order_by(order_by)
122
+
123
+ # Get total count
124
+ total_count = await queryset.acount()
125
+
126
+ # Apply pagination
127
+ queryset = queryset[offset:offset + limit]
128
+
129
+ # Serialize objects
130
+ objects = []
131
+ async for obj in queryset:
132
+ objects.append(self._serialize_object(obj))
133
+
134
+ return {
135
+ 'objects': objects,
136
+ 'total_count': total_count,
137
+ 'limit': limit,
138
+ 'offset': offset,
139
+ 'has_next': offset + limit < total_count,
140
+ 'has_previous': offset > 0,
141
+ }
142
+
143
+ async def aggregate_data(
144
+ self,
145
+ ctx: RunContext[DjangoDeps],
146
+ app_label: str,
147
+ model_name: str,
148
+ aggregations: Dict[str, str],
149
+ filters: Optional[Dict[str, Any]] = None,
150
+ group_by: Optional[str] = None
151
+ ) -> Dict[str, Any]:
152
+ """Perform aggregations on model data."""
153
+ from django.db.models import Count, Sum, Avg, Max, Min
154
+
155
+ model = self._get_model(app_label, model_name)
156
+
157
+ queryset = model.objects.all()
158
+
159
+ # Apply filters
160
+ if filters:
161
+ safe_filters = self._sanitize_filters(filters)
162
+ queryset = queryset.filter(**safe_filters)
163
+
164
+ # Prepare aggregation functions
165
+ agg_functions = {
166
+ 'count': Count,
167
+ 'sum': Sum,
168
+ 'avg': Avg,
169
+ 'max': Max,
170
+ 'min': Min,
171
+ }
172
+
173
+ agg_kwargs = {}
174
+ for alias, agg_spec in aggregations.items():
175
+ if ':' in agg_spec:
176
+ func_name, field_name = agg_spec.split(':', 1)
177
+ else:
178
+ func_name = agg_spec
179
+ field_name = 'id' # Default field
180
+
181
+ if func_name.lower() in agg_functions:
182
+ agg_func = agg_functions[func_name.lower()]
183
+ if func_name.lower() == 'count':
184
+ agg_kwargs[alias] = agg_func(field_name)
185
+ else:
186
+ agg_kwargs[alias] = agg_func(field_name)
187
+
188
+ # Perform aggregation
189
+ if group_by and hasattr(model, group_by):
190
+ # Group by field
191
+ result = []
192
+ async for item in queryset.values(group_by).annotate(**agg_kwargs):
193
+ result.append(item)
194
+ return {'grouped_results': result}
195
+ else:
196
+ # Simple aggregation
197
+ result = await queryset.aaggregate(**agg_kwargs)
198
+ return result
199
+
200
+ async def search_objects(
201
+ self,
202
+ ctx: RunContext[DjangoDeps],
203
+ app_label: str,
204
+ model_name: str,
205
+ search_fields: List[str],
206
+ query: str,
207
+ limit: int = 10
208
+ ) -> List[Dict[str, Any]]:
209
+ """Search objects using icontains on specified fields."""
210
+ from django.db.models import Q
211
+
212
+ model = self._get_model(app_label, model_name)
213
+
214
+ # Build search query
215
+ search_q = Q()
216
+ for field in search_fields:
217
+ if hasattr(model, field):
218
+ search_q |= Q(**{f"{field}__icontains": query})
219
+
220
+ if not search_q:
221
+ return []
222
+
223
+ # Execute search
224
+ queryset = model.objects.filter(search_q)[:limit]
225
+
226
+ results = []
227
+ async for obj in queryset:
228
+ results.append(self._serialize_object(obj))
229
+
230
+ return results
231
+
232
+ async def get_related_objects(
233
+ self,
234
+ ctx: RunContext[DjangoDeps],
235
+ app_label: str,
236
+ model_name: str,
237
+ object_id: Union[int, str],
238
+ relation_name: str,
239
+ limit: int = 10
240
+ ) -> List[Dict[str, Any]]:
241
+ """Get related objects through foreign key or many-to-many."""
242
+ model = self._get_model(app_label, model_name)
243
+
244
+ try:
245
+ obj = await model.objects.aget(pk=object_id)
246
+ except model.DoesNotExist:
247
+ return []
248
+
249
+ # Check if relation exists
250
+ if not hasattr(obj, relation_name):
251
+ return []
252
+
253
+ relation = getattr(obj, relation_name)
254
+
255
+ # Handle different relation types
256
+ if hasattr(relation, 'all'):
257
+ # Many-to-many or reverse foreign key
258
+ related_objects = relation.all()[:limit]
259
+ else:
260
+ # Single related object
261
+ if relation:
262
+ return [self._serialize_object(relation)]
263
+ else:
264
+ return []
265
+
266
+ results = []
267
+ async for related_obj in related_objects:
268
+ results.append(self._serialize_object(related_obj))
269
+
270
+ return results
271
+
272
+ def _sanitize_filters(self, filters: Dict[str, Any]) -> Dict[str, Any]:
273
+ """Sanitize filters to prevent dangerous operations."""
274
+ safe_filters = {}
275
+
276
+ # Allowed lookup types
277
+ allowed_lookups = {
278
+ 'exact', 'iexact', 'contains', 'icontains', 'startswith', 'istartswith',
279
+ 'endswith', 'iendswith', 'gt', 'gte', 'lt', 'lte', 'in', 'isnull',
280
+ 'date', 'year', 'month', 'day', 'week_day', 'hour', 'minute', 'second'
281
+ }
282
+
283
+ for key, value in filters.items():
284
+ # Check for dangerous operations
285
+ if '__' in key:
286
+ field, lookup = key.rsplit('__', 1)
287
+ if lookup in allowed_lookups:
288
+ safe_filters[key] = value
289
+ else:
290
+ # Direct field lookup (exact)
291
+ safe_filters[key] = value
292
+
293
+ return safe_filters
294
+
295
+ def _serialize_object(self, obj: models.Model) -> Dict[str, Any]:
296
+ """Serialize Django model object to dictionary."""
297
+ data = {}
298
+
299
+ for field in obj._meta.fields:
300
+ value = getattr(obj, field.name)
301
+
302
+ # Handle special field types
303
+ if hasattr(value, 'isoformat'):
304
+ # DateTime fields
305
+ data[field.name] = value.isoformat()
306
+ elif hasattr(value, '__dict__') and hasattr(value, 'pk'):
307
+ # Related objects - just include ID and str representation
308
+ data[field.name] = {
309
+ 'id': value.pk,
310
+ 'str': str(value)
311
+ }
312
+ else:
313
+ data[field.name] = value
314
+
315
+ # Add primary key and string representation
316
+ data['pk'] = obj.pk
317
+ data['str'] = str(obj)
318
+
319
+ return data
@@ -0,0 +1,46 @@
1
+ """
2
+ Django Orchestrator URLs.
3
+
4
+ Provides API endpoints for agent management and execution.
5
+ """
6
+
7
+ from django.urls import path, include
8
+ from rest_framework.routers import DefaultRouter
9
+
10
+ # Import views when they're created
11
+ # from .api.views import AgentViewSet, WorkflowViewSet, ExecutionViewSet
12
+
13
+ app_name = 'django_orchestrator'
14
+
15
+ # Create router for API endpoints
16
+ router = DefaultRouter()
17
+
18
+ # Register viewsets when they're created
19
+ # router.register(r'agents', AgentViewSet, basename='agent')
20
+ # router.register(r'workflows', WorkflowViewSet, basename='workflow')
21
+ # router.register(r'executions', ExecutionViewSet, basename='execution')
22
+
23
+ urlpatterns = [
24
+ # API endpoints
25
+ path('api/', include(router.urls)),
26
+
27
+ # Health check endpoint
28
+ path('health/', lambda request: JsonResponse({'status': 'ok', 'service': 'django-orchestrator'}), name='health'),
29
+ ]
30
+
31
+ # For now, create a simple health endpoint
32
+ from django.http import JsonResponse
33
+
34
+ def health_check(request):
35
+ """Health check endpoint for Django Orchestrator."""
36
+ return JsonResponse({
37
+ 'status': 'ok',
38
+ 'service': 'django-orchestrator',
39
+ 'version': '0.1.0'
40
+ })
41
+
42
+ # Update urlpatterns with the actual function
43
+ urlpatterns = [
44
+ path('api/', include(router.urls)),
45
+ path('health/', health_check, name='health'),
46
+ ]
@@ -0,0 +1,150 @@
1
+ # Django CFG Knowledge Base
2
+
3
+ Enterprise-grade RAG (Retrieval-Augmented Generation) application built on Django with pgvector semantic search, Dramatiq background processing, and comprehensive API endpoints for document management and AI-powered chat.
4
+
5
+ ## Features
6
+
7
+ - 📄 **Document Management**: Upload, process, and manage documents with automatic chunking
8
+ - 🔍 **Semantic Search**: pgvector-powered cosine similarity search
9
+ - 🤖 **AI Chat**: RAG-powered conversational interface with context retrieval
10
+ - 👥 **Multi-tenant**: Complete user isolation and access control
11
+ - ⚡ **Background Processing**: Async document processing with Dramatiq
12
+ - 💰 **Cost Tracking**: Monitor LLM usage and costs
13
+ - 🎨 **Admin Interface**: Beautiful Unfold-styled admin with statistics
14
+ - 🔒 **Type Safety**: Pydantic v2 validation throughout
15
+ - ✅ **Full Testing**: Comprehensive test coverage
16
+
17
+ ## Quick Start
18
+
19
+ ### 1. Enable in Configuration
20
+
21
+ ```python
22
+ from django_cfg import DjangoConfig
23
+
24
+ class MyConfig(DjangoConfig):
25
+ enable_knowbase: bool = True
26
+
27
+ # Required for AI features
28
+ openai_api_key: str = "${OPENAI_API_KEY}"
29
+
30
+ # Optional: Configure similarity thresholds
31
+ knowbase_document_threshold: float = 0.7
32
+ knowbase_archive_threshold: float = 0.6
33
+ ```
34
+
35
+ ### 2. Add to INSTALLED_APPS
36
+
37
+ ```python
38
+ INSTALLED_APPS = [
39
+ # ... other apps
40
+ 'django_cfg.apps.knowbase',
41
+ ]
42
+ ```
43
+
44
+ ### 3. Run Migrations
45
+
46
+ ```bash
47
+ python manage.py migrate
48
+ ```
49
+
50
+ ### 4. Start Using
51
+
52
+ The Knowledge Base will be available at `/cfg/knowbase/` with:
53
+
54
+ - **Admin Interface**: Document and chat management
55
+ - **API Endpoints**: RESTful API for integration
56
+ - **Chat Interface**: AI-powered conversational search
57
+
58
+ ## Architecture
59
+
60
+ ### Models
61
+ - **Document**: File storage and metadata
62
+ - **DocumentChunk**: Text chunks with embeddings
63
+ - **ChatSession**: Conversation management
64
+ - **ChatMessage**: Individual messages with context
65
+
66
+ ### Services
67
+ - **DocumentService**: Document processing and management
68
+ - **ChatService**: AI chat with RAG capabilities
69
+ - **SearchService**: Semantic search across all content types
70
+
71
+ ### Background Tasks
72
+ - Document processing and vectorization
73
+ - Embedding generation and optimization
74
+ - Maintenance and cleanup tasks
75
+
76
+ ## Configuration Options
77
+
78
+ ```python
79
+ class MyConfig(DjangoConfig):
80
+ # Enable/disable the app
81
+ enable_knowbase: bool = True
82
+
83
+ # AI Configuration
84
+ openai_api_key: str = "${OPENAI_API_KEY}"
85
+
86
+ # Search Thresholds
87
+ knowbase_document_threshold: float = 0.7 # Document similarity
88
+ knowbase_archive_threshold: float = 0.6 # Code similarity
89
+
90
+ # Processing Settings
91
+ knowbase_chunk_size: int = 1000 # Text chunk size
92
+ knowbase_overlap_size: int = 200 # Chunk overlap
93
+ knowbase_batch_size: int = 50 # Embedding batch size
94
+ ```
95
+
96
+ ## API Usage
97
+
98
+ ### Document Upload
99
+
100
+ ```python
101
+ import requests
102
+
103
+ response = requests.post('/cfg/knowbase/api/documents/', {
104
+ 'title': 'My Document',
105
+ 'file': open('document.pdf', 'rb')
106
+ })
107
+ ```
108
+
109
+ ### Chat Query
110
+
111
+ ```python
112
+ response = requests.post('/cfg/knowbase/api/chat/sessions/{session_id}/query/', {
113
+ 'query': 'What is machine learning?',
114
+ 'max_tokens': 500
115
+ })
116
+ ```
117
+
118
+ ### Search Documents
119
+
120
+ ```python
121
+ response = requests.get('/cfg/knowbase/api/search/', {
122
+ 'query': 'artificial intelligence',
123
+ 'limit': 10
124
+ })
125
+ ```
126
+
127
+ ## Integration with External Apps
128
+
129
+ The Knowledge Base supports integration with external Django apps through the `ExternalDataMixin`:
130
+
131
+ ```python
132
+ from django_cfg.apps.knowbase.mixins import ExternalDataMixin
133
+
134
+ class MyModel(ExternalDataMixin, models.Model):
135
+ name = models.CharField(max_length=100)
136
+ description = models.TextField()
137
+
138
+ # That's it! Auto AI integration enabled
139
+ ```
140
+
141
+ ## Requirements
142
+
143
+ - **PostgreSQL** with pgvector extension
144
+ - **Redis** for Dramatiq task queue
145
+ - **OpenAI API Key** for embeddings and chat
146
+ - **Python 3.11+** and **Django 5.0+**
147
+
148
+ ## License
149
+
150
+ Part of Django CFG - MIT License
@@ -0,0 +1,27 @@
1
+ """
2
+ Django SaaS Knowledge Assistant
3
+
4
+ Enterprise-grade RAG (Retrieval-Augmented Generation) application built on Django 5.2
5
+ with pgvector semantic search, Dramatiq background processing, and comprehensive
6
+ API endpoints for document management and AI-powered chat.
7
+
8
+ Key Features:
9
+ - Document ingestion with automatic chunking and embedding generation
10
+ - Semantic search using pgvector cosine similarity
11
+ - RAG-powered chat with context retrieval
12
+ - Multi-tenant user isolation
13
+ - Background processing with Dramatiq
14
+ - Cost tracking for LLM usage monitoring
15
+ - Comprehensive admin interface with Unfold styling
16
+ - Type-safe APIs with Pydantic v2 validation
17
+ - Full test coverage
18
+
19
+ Architecture:
20
+ - Models: Document, DocumentChunk, ChatSession, ChatMessage
21
+ - Services: DocumentService, ChatService, SearchService
22
+ - Tasks: Async document processing, maintenance, optimization
23
+ - APIs: REST endpoints with DRF and OpenAPI documentation
24
+ - Admin: Unfold-optimized interfaces with statistics
25
+ """
26
+
27
+ default_app_config = 'django_cfg.apps.knowbase.apps.KnowbaseConfig'
@@ -0,0 +1,23 @@
1
+ """
2
+ Knowledge Base Admin Configuration
3
+
4
+ Unfold-optimized admin interfaces for knowledge management.
5
+ """
6
+
7
+ from .document_admin import *
8
+ from .chat_admin import *
9
+ from .archive_admin import *
10
+ from .external_data_admin import *
11
+
12
+ __all__ = [
13
+ 'DocumentCategoryAdmin',
14
+ 'DocumentAdmin',
15
+ 'DocumentChunkAdmin',
16
+ 'DocumentArchiveAdmin',
17
+ 'ArchiveItemAdmin',
18
+ 'ArchiveItemChunkAdmin',
19
+ 'ExternalDataAdmin',
20
+ 'ExternalDataChunkAdmin',
21
+ 'ChatSessionAdmin',
22
+ 'ChatMessageAdmin',
23
+ ]