django-cfg 1.3.13__py3-none-any.whl → 1.4.3__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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/user_admin.py +39 -16
- django_cfg/apps/accounts/serializers/profile.py +1 -1
- django_cfg/apps/accounts/services/otp_service.py +18 -11
- django_cfg/apps/accounts/signals.py +15 -24
- django_cfg/apps/accounts/utils/notifications.py +217 -358
- django_cfg/apps/accounts/views/otp.py +2 -2
- django_cfg/apps/accounts/views/webhook.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +1 -1
- django_cfg/apps/agents/examples/__init__.py +3 -0
- django_cfg/apps/agents/examples/simple_example.py +161 -0
- django_cfg/apps/api/commands/views.py +66 -83
- django_cfg/apps/api/health/drf_views.py +269 -0
- django_cfg/apps/api/health/serializers.py +45 -0
- django_cfg/apps/api/health/urls.py +6 -1
- django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
- django_cfg/apps/knowbase/admin/document_admin.py +136 -270
- django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
- django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
- django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
- django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
- django_cfg/apps/knowbase/config/constance_fields.py +1 -1
- django_cfg/apps/knowbase/config/settings.py +2 -2
- django_cfg/apps/knowbase/examples/__init__.py +3 -0
- django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
- django_cfg/apps/knowbase/mixins/__init__.py +19 -2
- django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
- django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
- django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
- django_cfg/apps/knowbase/mixins/creator.py +10 -10
- django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +199 -0
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
- django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
- django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
- django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
- django_cfg/apps/knowbase/mixins/service.py +2 -2
- django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
- django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
- django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
- django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
- django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
- django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
- django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
- django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
- django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
- django_cfg/apps/knowbase/services/embedding/models.py +18 -14
- django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
- django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
- django_cfg/apps/leads/tests.py +1 -1
- django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
- django_cfg/apps/payments/admin/balance_admin.py +1 -1
- django_cfg/apps/payments/admin/currencies_admin.py +1 -1
- django_cfg/apps/payments/admin/payments_admin.py +1 -1
- django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
- django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
- django_cfg/apps/payments/admin_interface/views/base.py +29 -2
- django_cfg/apps/payments/apps.py +1 -1
- django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
- django_cfg/apps/payments/config/helpers.py +3 -2
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
- django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
- django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
- django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
- django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
- django_cfg/apps/payments/management/commands/test_providers.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +1 -1
- django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
- django_cfg/apps/payments/models/balance.py +2 -2
- django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
- django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
- django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
- django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
- django_cfg/apps/payments/models/payments.py +2 -2
- django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
- django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
- django_cfg/apps/payments/services/core/base.py +1 -1
- django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
- django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
- django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
- django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
- django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
- django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
- django_cfg/apps/payments/services/core/payment_service.py +124 -612
- django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
- django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
- django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
- django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
- django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
- django_cfg/apps/payments/services/providers/base.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
- django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
- django_cfg/apps/payments/services/providers/registry.py +1 -1
- django_cfg/apps/payments/services/providers/sync_service.py +1 -1
- django_cfg/apps/payments/signals/__init__.py +1 -1
- django_cfg/apps/payments/signals/api_key_signals.py +1 -1
- django_cfg/apps/payments/signals/balance_signals.py +1 -1
- django_cfg/apps/payments/signals/payment_signals.py +1 -1
- django_cfg/apps/payments/signals/subscription_signals.py +1 -1
- django_cfg/apps/payments/views/api/api_keys.py +1 -1
- django_cfg/apps/payments/views/api/balances.py +1 -1
- django_cfg/apps/payments/views/api/base.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +1 -1
- django_cfg/apps/payments/views/api/payments.py +1 -1
- django_cfg/apps/payments/views/api/subscriptions.py +1 -1
- django_cfg/apps/payments/views/api/webhooks.py +1 -1
- django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
- django_cfg/apps/payments/views/serializers/balances.py +1 -1
- django_cfg/apps/payments/views/serializers/currencies.py +1 -1
- django_cfg/apps/payments/views/serializers/payments.py +1 -1
- django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
- django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
- django_cfg/apps/support/admin/support_admin.py +21 -13
- django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
- django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
- django_cfg/apps/support/utils/support_email_service.py +1 -1
- django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
- django_cfg/apps/tasks/utils/simulator.py +1 -1
- django_cfg/apps/tasks/views/dashboard.py +33 -3
- django_cfg/apps/urls.py +5 -1
- django_cfg/cli/README.md +57 -471
- django_cfg/cli/commands/create_project.py +140 -529
- django_cfg/cli/main.py +13 -10
- django_cfg/core/__init__.py +63 -6
- django_cfg/core/base/__init__.py +5 -0
- django_cfg/core/base/config_model.py +652 -0
- django_cfg/core/builders/__init__.py +11 -0
- django_cfg/core/builders/apps_builder.py +258 -0
- django_cfg/core/builders/middleware_builder.py +115 -0
- django_cfg/core/builders/security_builder.py +96 -0
- django_cfg/core/config.py +20 -892
- django_cfg/core/constants.py +69 -0
- django_cfg/core/environment/__init__.py +9 -0
- django_cfg/core/exceptions.py +45 -298
- django_cfg/core/generation/__init__.py +51 -0
- django_cfg/core/generation/core_generators/__init__.py +0 -0
- django_cfg/core/generation/core_generators/settings.py +90 -0
- django_cfg/core/generation/core_generators/static.py +82 -0
- django_cfg/core/generation/core_generators/templates.py +141 -0
- django_cfg/core/generation/data_generators/__init__.py +15 -0
- django_cfg/core/generation/data_generators/cache.py +132 -0
- django_cfg/core/generation/data_generators/database.py +117 -0
- django_cfg/core/generation/generation.py +92 -0
- django_cfg/core/generation/integration_generators/__init__.py +21 -0
- django_cfg/core/generation/integration_generators/api.py +237 -0
- django_cfg/core/generation/integration_generators/sessions.py +65 -0
- django_cfg/core/generation/integration_generators/tailwind.py +54 -0
- django_cfg/core/generation/integration_generators/tasks.py +92 -0
- django_cfg/core/generation/integration_generators/third_party.py +144 -0
- django_cfg/core/generation/orchestrator.py +285 -0
- django_cfg/core/generation/protocols.py +30 -0
- django_cfg/core/generation/security_generators/__init__.py +0 -0
- django_cfg/core/generation/utility_generators/__init__.py +24 -0
- django_cfg/core/generation/utility_generators/email.py +58 -0
- django_cfg/core/generation/utility_generators/i18n.py +66 -0
- django_cfg/core/generation/utility_generators/limits.py +58 -0
- django_cfg/core/generation/utility_generators/logging.py +66 -0
- django_cfg/core/generation/utility_generators/security.py +101 -0
- django_cfg/core/generation/utils/__init__.py +0 -0
- django_cfg/core/generation/utils/helpers.py +32 -0
- django_cfg/core/integration/__init__.py +18 -25
- django_cfg/core/integration/display/startup.py +146 -133
- django_cfg/core/integration/url_integration.py +13 -2
- django_cfg/core/services/__init__.py +5 -0
- django_cfg/core/services/config_service.py +121 -0
- django_cfg/core/state/__init__.py +9 -0
- django_cfg/core/state/registry.py +84 -0
- django_cfg/core/types/__init__.py +15 -0
- django_cfg/core/types/aliases.py +15 -0
- django_cfg/core/types/enums.py +49 -0
- django_cfg/dashboard/DEBUG_README.md +105 -0
- django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
- django_cfg/dashboard/__init__.py +24 -0
- django_cfg/dashboard/components.py +308 -0
- django_cfg/dashboard/debug.py +176 -0
- django_cfg/dashboard/management/__init__.py +0 -0
- django_cfg/dashboard/management/commands/__init__.py +0 -0
- django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
- django_cfg/dashboard/sections/__init__.py +1 -0
- django_cfg/dashboard/sections/base.py +128 -0
- django_cfg/dashboard/sections/commands.py +32 -0
- django_cfg/dashboard/sections/overview.py +394 -0
- django_cfg/dashboard/sections/stats.py +48 -0
- django_cfg/dashboard/sections/system.py +73 -0
- django_cfg/management/commands/check_settings.py +6 -2
- django_cfg/management/commands/clear_constance.py +6 -1
- django_cfg/management/commands/create_token.py +5 -4
- django_cfg/management/commands/generate.py +5 -0
- django_cfg/management/commands/list_urls.py +7 -2
- django_cfg/management/commands/migrate_all.py +6 -2
- django_cfg/management/commands/migrator.py +6 -1
- django_cfg/management/commands/rundramatiq.py +6 -1
- django_cfg/management/commands/rundramatiq_simulator.py +11 -4
- django_cfg/management/commands/runserver_ngrok.py +9 -7
- django_cfg/management/commands/script.py +25 -21
- django_cfg/management/commands/show_config.py +6 -1
- django_cfg/management/commands/show_urls.py +8 -3
- django_cfg/management/commands/superuser.py +5 -4
- django_cfg/management/commands/task_clear.py +8 -3
- django_cfg/management/commands/task_status.py +8 -3
- django_cfg/management/commands/test_email.py +6 -1
- django_cfg/management/commands/test_telegram.py +6 -1
- django_cfg/management/commands/test_twilio.py +6 -1
- django_cfg/management/commands/tree.py +7 -4
- django_cfg/models/__init__.py +88 -3
- django_cfg/models/api/__init__.py +27 -0
- django_cfg/models/{api.py → api/config.py} +1 -1
- django_cfg/models/api/drf/__init__.py +21 -0
- django_cfg/models/api/drf/config.py +101 -0
- django_cfg/models/api/drf/redoc.py +31 -0
- django_cfg/models/api/drf/spectacular.py +129 -0
- django_cfg/models/api/drf/swagger.py +59 -0
- django_cfg/models/{api_keys.py → api/keys.py} +16 -6
- django_cfg/models/{limits.py → api/limits.py} +0 -1
- django_cfg/models/base/__init__.py +14 -0
- django_cfg/models/django/__init__.py +16 -0
- django_cfg/models/{constance.py → django/constance.py} +1 -1
- django_cfg/models/{environment.py → django/environment.py} +1 -1
- django_cfg/models/infrastructure/__init__.py +17 -0
- django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
- django_cfg/models/infrastructure/database/__init__.py +22 -0
- django_cfg/models/infrastructure/database/config.py +265 -0
- django_cfg/models/infrastructure/database/converters.py +91 -0
- django_cfg/models/infrastructure/database/parsers.py +96 -0
- django_cfg/models/infrastructure/database/routing.py +85 -0
- django_cfg/models/infrastructure/database/validators.py +170 -0
- django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
- django_cfg/models/{security.py → infrastructure/security.py} +2 -2
- django_cfg/models/ngrok/__init__.py +11 -0
- django_cfg/models/ngrok/auth.py +37 -0
- django_cfg/models/ngrok/config.py +77 -0
- django_cfg/models/ngrok/tunnel.py +35 -0
- django_cfg/models/payments/__init__.py +20 -0
- django_cfg/models/payments/api_keys.py +57 -0
- django_cfg/models/{payments.py → payments/config.py} +56 -154
- django_cfg/models/payments/providers/__init__.py +15 -0
- django_cfg/models/payments/providers/base.py +25 -0
- django_cfg/models/payments/providers/nowpayments.py +48 -0
- django_cfg/models/services/__init__.py +18 -0
- django_cfg/models/services/base.py +65 -0
- django_cfg/models/{email.py → services/email.py} +1 -1
- django_cfg/models/services/telegram.py +172 -0
- django_cfg/models/tasks/__init__.py +51 -0
- django_cfg/models/tasks/backends.py +250 -0
- django_cfg/models/tasks/config.py +314 -0
- django_cfg/models/tasks/utils.py +174 -0
- django_cfg/modules/base.py +18 -3
- django_cfg/modules/django_admin/decorators/actions.py +1 -1
- django_cfg/modules/django_admin/decorators/display.py +1 -1
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
- django_cfg/modules/django_currency/examples/__init__.py +3 -0
- django_cfg/modules/django_currency/examples/example_database_usage.py +144 -0
- django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
- django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
- django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
- django_cfg/modules/django_drf_theme/README.md +207 -0
- django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
- django_cfg/modules/django_drf_theme/__init__.py +23 -0
- django_cfg/modules/django_drf_theme/apps.py +15 -0
- django_cfg/modules/django_drf_theme/renderers.py +58 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
- django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
- django_cfg/modules/django_email/__init__.py +14 -0
- django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
- django_cfg/modules/django_email/utils.py +40 -0
- django_cfg/modules/django_health/__init__.py +9 -0
- django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
- django_cfg/modules/django_ipc_client/README.md +346 -0
- django_cfg/modules/django_ipc_client/__init__.py +51 -0
- django_cfg/modules/django_ipc_client/client.py +540 -0
- django_cfg/modules/django_ipc_client/config.py +207 -0
- django_cfg/modules/django_ipc_client/dashboard/README.md +517 -0
- django_cfg/modules/django_ipc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
- django_cfg/modules/django_ipc_client/dashboard/__init__.py +11 -0
- django_cfg/modules/django_ipc_client/dashboard/apps.py +22 -0
- django_cfg/modules/django_ipc_client/dashboard/monitor.py +435 -0
- django_cfg/modules/django_ipc_client/dashboard/static/django_ipc_dashboard/js/dashboard.js +373 -0
- django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/base.html +76 -0
- django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/dashboard.html +200 -0
- django_cfg/modules/django_ipc_client/dashboard/urls.py +22 -0
- django_cfg/modules/django_ipc_client/dashboard/urls_admin.py +9 -0
- django_cfg/modules/django_ipc_client/dashboard/views.py +251 -0
- django_cfg/modules/django_ipc_client/exceptions.py +201 -0
- django_cfg/modules/django_llm/llm/client.py +155 -550
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
- django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
- django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
- django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
- django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
- django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
- django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
- django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
- django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
- django_cfg/modules/django_llm/translator/translator.py +150 -603
- django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
- django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
- django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
- django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
- django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
- django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
- django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
- django_cfg/modules/django_logging/__init__.py +14 -0
- django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
- django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
- django_cfg/modules/django_ngrok/__init__.py +39 -0
- django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
- django_cfg/modules/django_rpc_old/POETRY.md +344 -0
- django_cfg/modules/django_rpc_old/README.md +397 -0
- django_cfg/modules/django_rpc_old/TESTING.md +358 -0
- django_cfg/modules/django_rpc_old/__init__.py +39 -0
- django_cfg/modules/django_rpc_old/client.py +531 -0
- django_cfg/modules/django_rpc_old/config.py +279 -0
- django_cfg/modules/django_rpc_old/exceptions.py +172 -0
- django_cfg/modules/django_tailwind/README.md +478 -0
- django_cfg/modules/django_tailwind/__init__.py +7 -0
- django_cfg/modules/django_tailwind/apps.py +10 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
- django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
- django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
- django_cfg/modules/django_tasks/__init__.py +29 -0
- django_cfg/modules/django_tasks/factory.py +127 -0
- django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
- django_cfg/modules/django_tasks/settings.py +107 -0
- django_cfg/modules/django_telegram/__init__.py +29 -0
- django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
- django_cfg/modules/django_telegram/utils.py +62 -0
- django_cfg/modules/django_twilio/__init__.py +54 -107
- django_cfg/modules/django_twilio/_imports.py +30 -0
- django_cfg/modules/django_twilio/base.py +192 -0
- django_cfg/modules/django_twilio/email_otp.py +227 -0
- django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
- django_cfg/modules/django_twilio/simple_service.py +1 -2
- django_cfg/modules/django_twilio/sms.py +94 -0
- django_cfg/modules/django_twilio/twilio_service.py +2 -3
- django_cfg/modules/django_twilio/unified.py +310 -0
- django_cfg/modules/django_twilio/utils.py +190 -0
- django_cfg/modules/django_twilio/whatsapp.py +137 -0
- django_cfg/modules/django_unfold/callbacks/base.py +198 -7
- django_cfg/modules/django_unfold/callbacks/main.py +102 -10
- django_cfg/modules/django_unfold/dashboard.py +65 -43
- django_cfg/modules/django_unfold/models/config.py +13 -12
- django_cfg/modules/django_unfold/models/navigation.py +8 -3
- django_cfg/modules/django_unfold/models/tabs.py +2 -2
- django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
- django_cfg/registry/core.py +24 -26
- django_cfg/registry/modules.py +5 -2
- django_cfg/registry/services.py +20 -3
- django_cfg/registry/third_party.py +8 -8
- django_cfg/static/admin/css/dashboard.css +260 -0
- django_cfg/static/admin/js/commands.js +171 -0
- django_cfg/static/admin/js/dashboard.js +126 -0
- django_cfg/templates/admin/components/management_commands.js +375 -0
- django_cfg/templates/admin/components/progress_bar.html +18 -23
- django_cfg/templates/admin/examples/component_class_example.html +156 -0
- django_cfg/templates/admin/index.html +48 -20
- django_cfg/templates/admin/index_new.html +106 -0
- django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
- django_cfg/templates/admin/sections/commands_section.html +626 -0
- django_cfg/templates/admin/sections/overview_section.html +112 -0
- django_cfg/templates/admin/sections/stats_section.html +35 -0
- django_cfg/templates/admin/sections/system_section.html +99 -0
- django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
- django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
- django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
- django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
- django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
- django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
- django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
- django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
- django_cfg/templatetags/django_cfg.py +7 -1
- django_cfg/utils/smart_defaults.py +4 -4
- django_cfg-1.4.3.dist-info/METADATA +533 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/RECORD +432 -195
- django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
- django_cfg/core/generation.py +0 -621
- django_cfg/management/commands/validate_config.py +0 -189
- django_cfg/models/database.py +0 -480
- django_cfg/models/drf.py +0 -272
- django_cfg/models/ngrok.py +0 -122
- django_cfg/models/services.py +0 -440
- django_cfg/models/tasks.py +0 -550
- django_cfg/modules/django_twilio/service.py +0 -942
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/rest_framework/api.html +0 -12
- django_cfg/utils/toolkit.py +0 -703
- django_cfg-1.3.13.dist-info/METADATA +0 -1029
- /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
- /django_cfg/core/{environment.py → environment/detector.py} +0 -0
- /django_cfg/models/{cors.py → api/cors.py} +0 -0
- /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
- /django_cfg/models/{base.py → base/config.py} +0 -0
- /django_cfg/models/{cfg.py → base/module.py} +0 -0
- /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
- /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
"""
|
2
|
+
Request handling for LLM client.
|
3
|
+
|
4
|
+
Handles chat completion and embedding requests with caching.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from .cache_manager import RequestCacheManager
|
8
|
+
from .chat_handler import ChatRequestHandler
|
9
|
+
from .embedding_handler import EmbeddingRequestHandler
|
10
|
+
|
11
|
+
__all__ = [
|
12
|
+
'RequestCacheManager',
|
13
|
+
'ChatRequestHandler',
|
14
|
+
'EmbeddingRequestHandler',
|
15
|
+
]
|
@@ -0,0 +1,170 @@
|
|
1
|
+
"""
|
2
|
+
Cache manager for LLM requests.
|
3
|
+
|
4
|
+
Manages caching of chat and embedding requests.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import logging
|
8
|
+
from typing import Optional, Dict, Any, List
|
9
|
+
from pathlib import Path
|
10
|
+
|
11
|
+
from ..cache import LLMCache
|
12
|
+
from ..models import ChatCompletionResponse, EmbeddingResponse
|
13
|
+
|
14
|
+
logger = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
|
17
|
+
class RequestCacheManager:
|
18
|
+
"""Manages caching for LLM requests."""
|
19
|
+
|
20
|
+
def __init__(
|
21
|
+
self,
|
22
|
+
cache_dir: Optional[Path] = None,
|
23
|
+
cache_ttl: int = 3600,
|
24
|
+
max_cache_size: int = 1000
|
25
|
+
):
|
26
|
+
"""
|
27
|
+
Initialize cache manager.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
cache_dir: Cache directory path
|
31
|
+
cache_ttl: Cache TTL in seconds
|
32
|
+
max_cache_size: Maximum cache size
|
33
|
+
"""
|
34
|
+
self.cache = LLMCache(
|
35
|
+
cache_dir=cache_dir,
|
36
|
+
ttl=cache_ttl,
|
37
|
+
max_size=max_cache_size
|
38
|
+
)
|
39
|
+
|
40
|
+
def get_cached_chat(
|
41
|
+
self,
|
42
|
+
messages: List[Dict[str, str]],
|
43
|
+
model: str,
|
44
|
+
max_tokens: Optional[int] = None,
|
45
|
+
temperature: Optional[float] = None,
|
46
|
+
response_format: Optional[str] = None,
|
47
|
+
**kwargs
|
48
|
+
) -> Optional[ChatCompletionResponse]:
|
49
|
+
"""
|
50
|
+
Get cached chat completion response.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
messages: Chat messages
|
54
|
+
model: Model used
|
55
|
+
max_tokens: Max tokens
|
56
|
+
temperature: Temperature
|
57
|
+
response_format: Response format
|
58
|
+
**kwargs: Additional parameters
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
Cached response or None
|
62
|
+
"""
|
63
|
+
request_hash = self.cache.generate_request_hash(
|
64
|
+
messages=messages,
|
65
|
+
model=model,
|
66
|
+
max_tokens=max_tokens,
|
67
|
+
temperature=temperature,
|
68
|
+
response_format=response_format,
|
69
|
+
**kwargs
|
70
|
+
)
|
71
|
+
|
72
|
+
cached_response = self.cache.get_response(request_hash)
|
73
|
+
if cached_response:
|
74
|
+
logger.debug("Cache hit for chat completion")
|
75
|
+
return ChatCompletionResponse(**cached_response)
|
76
|
+
|
77
|
+
return None
|
78
|
+
|
79
|
+
def cache_chat_response(
|
80
|
+
self,
|
81
|
+
response: ChatCompletionResponse,
|
82
|
+
messages: List[Dict[str, str]],
|
83
|
+
model: str,
|
84
|
+
max_tokens: Optional[int] = None,
|
85
|
+
temperature: Optional[float] = None,
|
86
|
+
response_format: Optional[str] = None,
|
87
|
+
**kwargs
|
88
|
+
):
|
89
|
+
"""
|
90
|
+
Cache chat completion response.
|
91
|
+
|
92
|
+
Args:
|
93
|
+
response: Response to cache
|
94
|
+
messages: Chat messages
|
95
|
+
model: Model used
|
96
|
+
max_tokens: Max tokens
|
97
|
+
temperature: Temperature
|
98
|
+
response_format: Response format
|
99
|
+
**kwargs: Additional parameters
|
100
|
+
"""
|
101
|
+
request_hash = self.cache.generate_request_hash(
|
102
|
+
messages=messages,
|
103
|
+
model=model,
|
104
|
+
max_tokens=max_tokens,
|
105
|
+
temperature=temperature,
|
106
|
+
response_format=response_format,
|
107
|
+
**kwargs
|
108
|
+
)
|
109
|
+
|
110
|
+
self.cache.set_response(request_hash, response.model_dump(), model)
|
111
|
+
logger.debug("Cached chat completion response")
|
112
|
+
|
113
|
+
def get_cached_embedding(
|
114
|
+
self,
|
115
|
+
text: str,
|
116
|
+
model: str
|
117
|
+
) -> Optional[EmbeddingResponse]:
|
118
|
+
"""
|
119
|
+
Get cached embedding response.
|
120
|
+
|
121
|
+
Args:
|
122
|
+
text: Input text
|
123
|
+
model: Model used
|
124
|
+
|
125
|
+
Returns:
|
126
|
+
Cached response or None
|
127
|
+
"""
|
128
|
+
request_hash = self.cache.generate_request_hash(
|
129
|
+
messages=[{"role": "user", "content": text}],
|
130
|
+
model=model,
|
131
|
+
task="embedding"
|
132
|
+
)
|
133
|
+
|
134
|
+
cached_response = self.cache.get_response(request_hash)
|
135
|
+
if cached_response:
|
136
|
+
logger.debug("Cache hit for embedding generation")
|
137
|
+
return EmbeddingResponse(**cached_response)
|
138
|
+
|
139
|
+
return None
|
140
|
+
|
141
|
+
def cache_embedding_response(
|
142
|
+
self,
|
143
|
+
response: EmbeddingResponse,
|
144
|
+
text: str,
|
145
|
+
model: str
|
146
|
+
):
|
147
|
+
"""
|
148
|
+
Cache embedding response.
|
149
|
+
|
150
|
+
Args:
|
151
|
+
response: Response to cache
|
152
|
+
text: Input text
|
153
|
+
model: Model used
|
154
|
+
"""
|
155
|
+
request_hash = self.cache.generate_request_hash(
|
156
|
+
messages=[{"role": "user", "content": text}],
|
157
|
+
model=model,
|
158
|
+
task="embedding"
|
159
|
+
)
|
160
|
+
|
161
|
+
self.cache.set_response(request_hash, response.model_dump(), model)
|
162
|
+
logger.debug("Cached embedding response")
|
163
|
+
|
164
|
+
def get_cache_info(self) -> Dict[str, Any]:
|
165
|
+
"""Get cache information."""
|
166
|
+
return self.cache.get_cache_info()
|
167
|
+
|
168
|
+
def clear_cache(self):
|
169
|
+
"""Clear the cache."""
|
170
|
+
self.cache.clear_cache()
|
@@ -0,0 +1,199 @@
|
|
1
|
+
"""
|
2
|
+
Chat request handler for LLM client.
|
3
|
+
|
4
|
+
Handles chat completion requests with caching and response building.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import time
|
8
|
+
import logging
|
9
|
+
from typing import List, Dict, Optional, TYPE_CHECKING
|
10
|
+
|
11
|
+
from ..models import ChatCompletionResponse
|
12
|
+
from ..providers import ConfigBuilder
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from ..providers import ProviderManager
|
16
|
+
from ..responses import ResponseBuilder
|
17
|
+
from ..stats import StatsManager
|
18
|
+
from .cache_manager import RequestCacheManager
|
19
|
+
|
20
|
+
logger = logging.getLogger(__name__)
|
21
|
+
|
22
|
+
|
23
|
+
class ChatRequestHandler:
|
24
|
+
"""Handles chat completion requests with caching."""
|
25
|
+
|
26
|
+
def __init__(
|
27
|
+
self,
|
28
|
+
provider_manager: 'ProviderManager',
|
29
|
+
cache_manager: 'RequestCacheManager',
|
30
|
+
stats_manager: 'StatsManager',
|
31
|
+
response_builder: 'ResponseBuilder',
|
32
|
+
tokenizer
|
33
|
+
):
|
34
|
+
"""
|
35
|
+
Initialize chat request handler.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
provider_manager: Provider manager instance
|
39
|
+
cache_manager: Cache manager instance
|
40
|
+
stats_manager: Stats manager instance
|
41
|
+
response_builder: Response builder instance
|
42
|
+
tokenizer: Tokenizer instance
|
43
|
+
"""
|
44
|
+
self.provider_manager = provider_manager
|
45
|
+
self.cache_manager = cache_manager
|
46
|
+
self.stats_manager = stats_manager
|
47
|
+
self.response_builder = response_builder
|
48
|
+
self.tokenizer = tokenizer
|
49
|
+
|
50
|
+
def chat_completion(
|
51
|
+
self,
|
52
|
+
messages: List[Dict[str, str]],
|
53
|
+
model: Optional[str] = None,
|
54
|
+
max_tokens: Optional[int] = None,
|
55
|
+
temperature: Optional[float] = None,
|
56
|
+
response_format: Optional[str] = None,
|
57
|
+
**kwargs
|
58
|
+
) -> ChatCompletionResponse:
|
59
|
+
"""
|
60
|
+
Execute chat completion with caching.
|
61
|
+
|
62
|
+
Args:
|
63
|
+
messages: List of chat messages
|
64
|
+
model: Model to use
|
65
|
+
max_tokens: Maximum tokens
|
66
|
+
temperature: Temperature for generation
|
67
|
+
response_format: Response format (e.g., "json")
|
68
|
+
**kwargs: Additional parameters
|
69
|
+
|
70
|
+
Returns:
|
71
|
+
Chat completion response
|
72
|
+
|
73
|
+
Raises:
|
74
|
+
RuntimeError: If client is not initialized or request fails
|
75
|
+
"""
|
76
|
+
# Get client and provider
|
77
|
+
client = self.provider_manager.primary_client
|
78
|
+
provider = self.provider_manager.primary_provider
|
79
|
+
|
80
|
+
if not client:
|
81
|
+
raise RuntimeError("OpenAI client not initialized")
|
82
|
+
|
83
|
+
# Use default model if needed
|
84
|
+
if model is None:
|
85
|
+
model = ConfigBuilder.get_default_model(provider)
|
86
|
+
|
87
|
+
# Prepare API model (remove prefix for OpenAI)
|
88
|
+
api_model = self._prepare_api_model(model, provider)
|
89
|
+
|
90
|
+
# Check cache
|
91
|
+
cached_response = self.cache_manager.get_cached_chat(
|
92
|
+
messages, model, max_tokens, temperature, response_format, **kwargs
|
93
|
+
)
|
94
|
+
if cached_response:
|
95
|
+
self.stats_manager.record_cache_hit()
|
96
|
+
return cached_response
|
97
|
+
|
98
|
+
self.stats_manager.record_cache_miss()
|
99
|
+
self.stats_manager.record_request()
|
100
|
+
|
101
|
+
# Estimate tokens
|
102
|
+
estimated_tokens = self.tokenizer.count_messages_tokens(messages, model)
|
103
|
+
logger.debug(f"Estimated input tokens: {estimated_tokens}")
|
104
|
+
|
105
|
+
# Make API call
|
106
|
+
start_time = time.time()
|
107
|
+
try:
|
108
|
+
api_response = self._make_api_call(
|
109
|
+
client, api_model, messages, max_tokens, temperature, response_format, **kwargs
|
110
|
+
)
|
111
|
+
processing_time = time.time() - start_time
|
112
|
+
|
113
|
+
# Build response object
|
114
|
+
completion_response = self.response_builder.build_chat_response(
|
115
|
+
api_response, model, provider, response_format, processing_time
|
116
|
+
)
|
117
|
+
|
118
|
+
# Cache response
|
119
|
+
self.cache_manager.cache_chat_response(
|
120
|
+
completion_response, messages, model, max_tokens, temperature, response_format, **kwargs
|
121
|
+
)
|
122
|
+
|
123
|
+
# Update stats
|
124
|
+
self.stats_manager.record_success(
|
125
|
+
tokens=completion_response.tokens_used,
|
126
|
+
cost=completion_response.cost_usd,
|
127
|
+
model=model,
|
128
|
+
provider=provider
|
129
|
+
)
|
130
|
+
|
131
|
+
return completion_response
|
132
|
+
|
133
|
+
except Exception as e:
|
134
|
+
self.stats_manager.record_failure()
|
135
|
+
logger.error(f"Chat completion failed: {e}")
|
136
|
+
raise
|
137
|
+
|
138
|
+
def _prepare_api_model(self, model: str, provider: str) -> str:
|
139
|
+
"""
|
140
|
+
Prepare model name for API call.
|
141
|
+
|
142
|
+
For OpenAI, remove provider prefix if present.
|
143
|
+
|
144
|
+
Args:
|
145
|
+
model: Model name
|
146
|
+
provider: Provider name
|
147
|
+
|
148
|
+
Returns:
|
149
|
+
API-ready model name
|
150
|
+
"""
|
151
|
+
api_model = model
|
152
|
+
if provider == "openai" and model.startswith("openai/"):
|
153
|
+
api_model = model.replace("openai/", "")
|
154
|
+
return api_model
|
155
|
+
|
156
|
+
def _make_api_call(
|
157
|
+
self,
|
158
|
+
client,
|
159
|
+
model: str,
|
160
|
+
messages: List[Dict[str, str]],
|
161
|
+
max_tokens: Optional[int],
|
162
|
+
temperature: Optional[float],
|
163
|
+
response_format: Optional[str],
|
164
|
+
**kwargs
|
165
|
+
):
|
166
|
+
"""
|
167
|
+
Make actual API call.
|
168
|
+
|
169
|
+
Args:
|
170
|
+
client: OpenAI client
|
171
|
+
model: Model to use
|
172
|
+
messages: Chat messages
|
173
|
+
max_tokens: Max tokens
|
174
|
+
temperature: Temperature
|
175
|
+
response_format: Response format
|
176
|
+
**kwargs: Additional parameters
|
177
|
+
|
178
|
+
Returns:
|
179
|
+
API response
|
180
|
+
"""
|
181
|
+
params = {
|
182
|
+
"model": model,
|
183
|
+
"messages": messages,
|
184
|
+
"stream": False
|
185
|
+
}
|
186
|
+
|
187
|
+
# Add optional parameters
|
188
|
+
if max_tokens is not None:
|
189
|
+
params["max_tokens"] = max_tokens
|
190
|
+
if temperature is not None:
|
191
|
+
params["temperature"] = temperature
|
192
|
+
if response_format:
|
193
|
+
params["response_format"] = {"type": response_format}
|
194
|
+
|
195
|
+
# Add any additional kwargs
|
196
|
+
params.update(kwargs)
|
197
|
+
|
198
|
+
logger.debug(f"Making chat completion request with model: {model}")
|
199
|
+
return client.chat.completions.create(**params)
|
@@ -0,0 +1,113 @@
|
|
1
|
+
"""
|
2
|
+
Embedding request handler for LLM client.
|
3
|
+
|
4
|
+
Handles embedding generation requests with provider-specific strategies.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import logging
|
8
|
+
from typing import TYPE_CHECKING
|
9
|
+
|
10
|
+
from ..models import EmbeddingResponse
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
from ..providers import ProviderManager, ProviderSelector
|
14
|
+
from ..embeddings import OpenAIEmbedder, MockEmbedder
|
15
|
+
from ..stats import StatsManager
|
16
|
+
from .cache_manager import RequestCacheManager
|
17
|
+
|
18
|
+
logger = logging.getLogger(__name__)
|
19
|
+
|
20
|
+
|
21
|
+
class EmbeddingRequestHandler:
|
22
|
+
"""Handles embedding generation requests."""
|
23
|
+
|
24
|
+
def __init__(
|
25
|
+
self,
|
26
|
+
provider_manager: 'ProviderManager',
|
27
|
+
provider_selector: 'ProviderSelector',
|
28
|
+
cache_manager: 'RequestCacheManager',
|
29
|
+
stats_manager: 'StatsManager',
|
30
|
+
openai_embedder: 'OpenAIEmbedder',
|
31
|
+
mock_embedder: 'MockEmbedder'
|
32
|
+
):
|
33
|
+
"""
|
34
|
+
Initialize embedding request handler.
|
35
|
+
|
36
|
+
Args:
|
37
|
+
provider_manager: Provider manager instance
|
38
|
+
provider_selector: Provider selector instance
|
39
|
+
cache_manager: Cache manager instance
|
40
|
+
stats_manager: Stats manager instance
|
41
|
+
openai_embedder: OpenAI embedder instance
|
42
|
+
mock_embedder: Mock embedder instance
|
43
|
+
"""
|
44
|
+
self.provider_manager = provider_manager
|
45
|
+
self.provider_selector = provider_selector
|
46
|
+
self.cache_manager = cache_manager
|
47
|
+
self.stats_manager = stats_manager
|
48
|
+
self.openai_embedder = openai_embedder
|
49
|
+
self.mock_embedder = mock_embedder
|
50
|
+
|
51
|
+
def generate_embedding(
|
52
|
+
self,
|
53
|
+
text: str,
|
54
|
+
model: str = "text-embedding-ada-002"
|
55
|
+
) -> EmbeddingResponse:
|
56
|
+
"""
|
57
|
+
Generate embedding with provider-specific logic.
|
58
|
+
|
59
|
+
Uses real OpenAI embeddings when available, falls back to mock
|
60
|
+
embeddings for providers without embedding support.
|
61
|
+
|
62
|
+
Args:
|
63
|
+
text: Text to generate embedding for
|
64
|
+
model: Embedding model to use
|
65
|
+
|
66
|
+
Returns:
|
67
|
+
Embedding response with vector and metadata
|
68
|
+
|
69
|
+
Raises:
|
70
|
+
RuntimeError: If embedding generation fails
|
71
|
+
"""
|
72
|
+
# Check cache
|
73
|
+
cached_response = self.cache_manager.get_cached_embedding(text, model)
|
74
|
+
if cached_response:
|
75
|
+
self.stats_manager.record_cache_hit()
|
76
|
+
return cached_response
|
77
|
+
|
78
|
+
self.stats_manager.record_cache_miss()
|
79
|
+
self.stats_manager.record_request()
|
80
|
+
|
81
|
+
# Get best provider for embedding
|
82
|
+
provider = self.provider_selector.get_provider_for_task("embedding")
|
83
|
+
|
84
|
+
try:
|
85
|
+
# Generate embedding using appropriate strategy
|
86
|
+
if self.provider_selector.should_use_mock_embedding(provider):
|
87
|
+
# Use mock embedder for OpenRouter
|
88
|
+
logger.debug(f"Using mock embedder for provider: {provider}")
|
89
|
+
result = self.mock_embedder.generate(text, model)
|
90
|
+
else:
|
91
|
+
# Use real OpenAI embeddings
|
92
|
+
logger.debug(f"Using OpenAI embedder for provider: {provider}")
|
93
|
+
client = self.provider_manager.get_client(provider)
|
94
|
+
result = self.openai_embedder.generate(client, text, model)
|
95
|
+
|
96
|
+
# Cache response
|
97
|
+
self.cache_manager.cache_embedding_response(result, text, model)
|
98
|
+
|
99
|
+
# Update stats
|
100
|
+
self.stats_manager.record_success(
|
101
|
+
tokens=result.tokens,
|
102
|
+
cost=result.cost,
|
103
|
+
model=model,
|
104
|
+
provider=provider
|
105
|
+
)
|
106
|
+
|
107
|
+
return result
|
108
|
+
|
109
|
+
except Exception as e:
|
110
|
+
self.stats_manager.record_failure()
|
111
|
+
error_msg = f"Embedding generation failed: {e}"
|
112
|
+
logger.error(error_msg)
|
113
|
+
raise RuntimeError(error_msg) from e
|
@@ -0,0 +1,131 @@
|
|
1
|
+
"""
|
2
|
+
Response builder for LLM client.
|
3
|
+
|
4
|
+
Builds Pydantic response objects from API responses.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import time
|
8
|
+
import logging
|
9
|
+
from datetime import datetime
|
10
|
+
from typing import Optional
|
11
|
+
from openai.types.chat import ChatCompletion
|
12
|
+
|
13
|
+
from ..costs import calculate_chat_cost
|
14
|
+
from ..models import ChatCompletionResponse, ChatChoice, TokenUsage
|
15
|
+
|
16
|
+
logger = logging.getLogger(__name__)
|
17
|
+
|
18
|
+
|
19
|
+
class ResponseBuilder:
|
20
|
+
"""Builds Pydantic response objects from API responses."""
|
21
|
+
|
22
|
+
def __init__(self, models_cache=None, json_extractor=None):
|
23
|
+
"""
|
24
|
+
Initialize response builder.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
models_cache: Optional models cache for cost calculation
|
28
|
+
json_extractor: Optional JSON extractor for parsing JSON responses
|
29
|
+
"""
|
30
|
+
self.models_cache = models_cache
|
31
|
+
self.json_extractor = json_extractor
|
32
|
+
|
33
|
+
def build_chat_response(
|
34
|
+
self,
|
35
|
+
api_response: ChatCompletion,
|
36
|
+
model: str,
|
37
|
+
provider: str,
|
38
|
+
response_format: Optional[str] = None,
|
39
|
+
processing_time: float = 0.0
|
40
|
+
) -> ChatCompletionResponse:
|
41
|
+
"""
|
42
|
+
Build ChatCompletionResponse from API response.
|
43
|
+
|
44
|
+
Args:
|
45
|
+
api_response: Raw API response from OpenAI
|
46
|
+
model: Model used for generation
|
47
|
+
provider: Provider used
|
48
|
+
response_format: Response format (e.g., "json")
|
49
|
+
processing_time: Time taken to process request
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
ChatCompletionResponse Pydantic model
|
53
|
+
"""
|
54
|
+
# Calculate cost
|
55
|
+
usage_dict = self._extract_usage(api_response)
|
56
|
+
cost_usd = calculate_chat_cost(usage_dict, model, self.models_cache)
|
57
|
+
|
58
|
+
# Extract content
|
59
|
+
content = self._extract_content(api_response)
|
60
|
+
|
61
|
+
# Try to extract JSON if requested
|
62
|
+
extracted_json = None
|
63
|
+
if response_format == "json" and content and self.json_extractor:
|
64
|
+
try:
|
65
|
+
extracted_json = self.json_extractor.extract_json_from_response(content)
|
66
|
+
except Exception as e:
|
67
|
+
logger.warning(f"Failed to extract JSON from response: {e}")
|
68
|
+
|
69
|
+
# Build response object
|
70
|
+
return ChatCompletionResponse(
|
71
|
+
id=api_response.id,
|
72
|
+
model=api_response.model,
|
73
|
+
created=datetime.fromtimestamp(api_response.created).isoformat(),
|
74
|
+
choices=self._build_choices(api_response),
|
75
|
+
usage=self._build_token_usage(api_response.usage),
|
76
|
+
finish_reason=self._extract_finish_reason(api_response),
|
77
|
+
content=content,
|
78
|
+
tokens_used=usage_dict['total_tokens'],
|
79
|
+
cost_usd=cost_usd,
|
80
|
+
processing_time=processing_time,
|
81
|
+
extracted_json=extracted_json
|
82
|
+
)
|
83
|
+
|
84
|
+
def _extract_usage(self, api_response: ChatCompletion) -> dict:
|
85
|
+
"""Extract usage dictionary from API response."""
|
86
|
+
if api_response.usage:
|
87
|
+
return api_response.usage.model_dump()
|
88
|
+
return {
|
89
|
+
'total_tokens': 0,
|
90
|
+
'prompt_tokens': 0,
|
91
|
+
'completion_tokens': 0
|
92
|
+
}
|
93
|
+
|
94
|
+
def _extract_content(self, api_response: ChatCompletion) -> str:
|
95
|
+
"""Extract content from API response."""
|
96
|
+
if api_response.choices and len(api_response.choices) > 0:
|
97
|
+
return api_response.choices[0].message.content or ""
|
98
|
+
return ""
|
99
|
+
|
100
|
+
def _extract_finish_reason(self, api_response: ChatCompletion) -> Optional[str]:
|
101
|
+
"""Extract finish reason from API response."""
|
102
|
+
if api_response.choices and len(api_response.choices) > 0:
|
103
|
+
return api_response.choices[0].finish_reason
|
104
|
+
return None
|
105
|
+
|
106
|
+
def _build_choices(self, api_response: ChatCompletion) -> list:
|
107
|
+
"""Build list of ChatChoice objects from API response."""
|
108
|
+
if not api_response.choices:
|
109
|
+
return []
|
110
|
+
|
111
|
+
return [
|
112
|
+
ChatChoice(
|
113
|
+
index=choice.index,
|
114
|
+
message=choice.message.model_dump() if hasattr(choice.message, 'model_dump') else choice.message,
|
115
|
+
finish_reason=choice.finish_reason
|
116
|
+
) for choice in api_response.choices
|
117
|
+
]
|
118
|
+
|
119
|
+
def _build_token_usage(self, usage) -> TokenUsage:
|
120
|
+
"""Build TokenUsage object from API response usage."""
|
121
|
+
if usage:
|
122
|
+
return TokenUsage(
|
123
|
+
prompt_tokens=usage.prompt_tokens,
|
124
|
+
completion_tokens=usage.completion_tokens,
|
125
|
+
total_tokens=usage.total_tokens
|
126
|
+
)
|
127
|
+
return TokenUsage(
|
128
|
+
prompt_tokens=0,
|
129
|
+
completion_tokens=0,
|
130
|
+
total_tokens=0
|
131
|
+
)
|