kaia-brainbox 0.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kaia_brainbox-0.0.0/PKG-INFO +637 -0
- kaia_brainbox-0.0.0/README.md +609 -0
- kaia_brainbox-0.0.0/brainbox/deciders/__init__.py +6 -0
- kaia_brainbox-0.0.0/brainbox/deciders/common/__init__.py +18 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/__init__.py +3 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/api.py +89 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/container/main.py +44 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/controller.py +166 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/model.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/run.py +12 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/settings.py +75 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/tests.py +69 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/workflows/__init__.py +5 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/workflows/template.py +133 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/workflows/text_to_image.py +31 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/workflows/upscale.py +18 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/workflows/wd14_interrogate.py +27 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/comfyui/workflows/workflow.py +15 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/api.py +38 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/container/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/container/main.py +18 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/container/model.py +5 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/container/server.py +102 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/controller.py +133 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/run.py +10 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/video_to_images/settings.py +5 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/api.py +49 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/container/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/container/main.py +7 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/container/server.py +121 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/container/validation_objects.py +11 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/controller.py +143 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/model.py +29 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/run.py +7 -0
- kaia_brainbox-0.0.0/brainbox/deciders/images/yolo/settings.py +11 -0
- kaia_brainbox-0.0.0/brainbox/deciders/plugins/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/text/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/text/ollama/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/text/ollama/api.py +50 -0
- kaia_brainbox-0.0.0/brainbox/deciders/text/ollama/controller.py +70 -0
- kaia_brainbox-0.0.0/brainbox/deciders/text/ollama/model.py +27 -0
- kaia_brainbox-0.0.0/brainbox/deciders/text/ollama/run.py +15 -0
- kaia_brainbox-0.0.0/brainbox/deciders/text/ollama/settings.py +10 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/__init__.py +4 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/api.py +47 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/container/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/container/main.py +20 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/container/server.py +51 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/controller.py +178 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/model.py +20 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/run.py +8 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/boilerplate/settings.py +9 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/collector/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/collector/collector.py +40 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/collector/collector_to_media_library_convertor.py +67 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/collector/functional_task_builder.py +19 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/collector/task_builder.py +61 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/fake_file.py +19 -0
- kaia_brainbox-0.0.0/brainbox/deciders/utils/fake_text.py +9 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/__init__.py +3 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/api.py +69 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/container/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/container/classifier.py +81 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/container/main.py +19 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/container/server.py +75 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/controller.py +236 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/produce_test_media_library.py +29 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/run.py +9 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/resemblyzer/settings.py +6 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/api.py +54 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/container/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/container/main.py +25 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/container/model.py +33 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/container/server.py +63 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/container/train.py +140 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/container/transcribe.py +52 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/container/utils.py +23 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/controller.py +67 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/model.py +38 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/run.py +7 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/settings.py +11 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/rhasspy_kaldi/tests.py +90 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/api.py +72 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/container/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/container/main.py +21 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/container/server.py +67 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/controller.py +201 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/model.py +25 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/run.py +6 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_analysis/whisper/settings.py +14 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/__init__.py +3 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/api.py +90 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/container/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/container/installer_script.py +5 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/container/main.py +49 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/container/server.py +125 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/container/tts_loader.py +38 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/controller.py +322 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/run.py +11 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/settings.py +28 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/coqui_tts/tests.py +71 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/open_tts/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/open_tts/api.py +36 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/open_tts/controller.py +45 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/open_tts/run.py +7 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/open_tts/settings.py +6 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/api.py +56 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/container/__init__.py +0 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/container/generate.py +59 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/container/main.py +64 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/controller.py +246 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/run.py +6 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/settings.py +9 -0
- kaia_brainbox-0.0.0/brainbox/deciders/voice_generation/tortoise_tts/upload_prerequisite.py +16 -0
- kaia_brainbox-0.0.0/brainbox/framework/__init__.py +6 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/__init__.py +9 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/__init__.py +4 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/api.py +123 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/html_helpers/__init__.py +3 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/html_helpers/batch_page.py +120 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/html_helpers/main_page.py +122 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/html_helpers/operator_log_page.py +16 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/interface.py +123 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/server.py +61 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/serverless_test.py +37 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/service.py +138 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/app/task.py +30 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/__init__.py +7 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/combined_task.py +31 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/command.py +18 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/extended_task.py +34 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/helper_methods.py +80 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/one_brainbox_task_factory.py +20 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/postprocessors.py +52 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/prerequisites.py +44 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/task.py +83 -0
- kaia_brainbox-0.0.0/brainbox/framework/brainbox/task/task_builder.py +99 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/__init__.py +9 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/api_utils.py +34 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/decider.py +62 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/file.py +99 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/file_io.py +63 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/file_like.py +68 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/fork.py +56 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/fork_worker.py +26 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/loc.py +105 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/logger.py +8 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/__init__.py +4 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/api.py +44 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/api_binding.py +35 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/endpoint.py +24 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/format.py +56 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/marshalling_metadata.py +38 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/server.py +43 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/server_binding.py +49 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/marshalling/test_api.py +27 -0
- kaia_brainbox-0.0.0/brainbox/framework/common/signature_processor.py +57 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/__init__.py +2 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/__init__.py +5 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/api.py +58 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/dto.py +47 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/html_helpers/__init__.py +2 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/html_helpers/installation_report_page.py +28 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/html_helpers/page.py +71 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/html_helpers/status_page.py +79 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/interface.py +57 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/logging.py +67 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/server.py +100 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/service.py +215 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/app/setuper.py +64 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/__init__.py +17 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/connection_settings.py +6 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/controller.py +156 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/controller_context.py +49 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/controller_over_decider.py +58 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/controller_registry.py +130 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/docker_controller.py +144 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/docker_web_service_api.py +41 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/docker_web_service_controller.py +66 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/model_downloading_controller.py +80 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/notebookable_controller.py +7 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/on_demand_docker_api.py +14 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/on_demand_docker_controller.py +19 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/resource_folder.py +14 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/run_configuration.py +88 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/runner.py +18 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/single_loadable_model_api.py +10 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/test_report/__init__.py +2 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/test_report/main_section_content.py +5 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/test_report/self_test_report_page.py +115 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/test_report/test_report.py +58 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/test_report/test_report_item.py +55 -0
- kaia_brainbox-0.0.0/brainbox/framework/controllers/controller/test_report/test_report_section.py +10 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/__init__.py +5 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/container_runner/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/container_runner/container_runner.py +58 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/deployment.py +69 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/__init__.py +8 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/command.py +15 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/executor.py +32 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/file_system.py +27 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/local_executor.py +53 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/local_file_system.py +28 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/machine.py +14 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/ssh_executor.py +41 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/executor/ssh_file_system.py +47 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_builder/__init__.py +2 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_builder/image_builder.py +9 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_builder/small_image_builder.py +120 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_source/__init__.py +5 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_source/docker_io_image_source.py +41 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_source/hacked_docker_io_image_source.py +16 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_source/image_source.py +38 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_source/local_image_source.py +25 -0
- kaia_brainbox-0.0.0/brainbox/framework/deployment/image_source/remote_public_image_source.py +22 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/__init__.py +4 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/__init__.py +8 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/core.py +47 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/decider_instance_key.py +10 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/job.py +61 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/job_for_planner.py +15 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/operator_log.py +78 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/operator_message.py +21 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/operator_state.py +37 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/core/trackable_session_factory.py +33 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/main_loop/__init__.py +6 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/main_loop/cancel_action.py +22 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/main_loop/check_ready_action.py +59 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/main_loop/main_loop.py +78 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/main_loop/remove_incorrect_action.py +13 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/main_loop/task_status_updater.py +52 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/main_loop/tasks_for_planner_sync.py +56 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/operator/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/operator/decider_log.py +14 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/operator/file_postprocessor.py +24 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/operator/operator.py +75 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner/__init__.py +5 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner/assign_action.py +55 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner/planner.py +20 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner/planner_action.py +4 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner/start_action.py +85 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner/stop_action.py +16 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner_implementation/__init__.py +2 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner_implementation/always_on_planner.py +24 -0
- kaia_brainbox-0.0.0/brainbox/framework/job_processing/planner_implementation/simple_planner.py +97 -0
- kaia_brainbox-0.0.0/brainbox/framework/media_library/__init__.py +1 -0
- kaia_brainbox-0.0.0/brainbox/framework/media_library/media_library.py +244 -0
- kaia_brainbox-0.0.0/kaia_brainbox.egg-info/PKG-INFO +637 -0
- kaia_brainbox-0.0.0/kaia_brainbox.egg-info/SOURCES.txt +261 -0
- kaia_brainbox-0.0.0/kaia_brainbox.egg-info/dependency_links.txt +1 -0
- kaia_brainbox-0.0.0/kaia_brainbox.egg-info/requires.txt +9 -0
- kaia_brainbox-0.0.0/kaia_brainbox.egg-info/top_level.txt +2 -0
- kaia_brainbox-0.0.0/pyproject.toml +49 -0
- kaia_brainbox-0.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: kaia-brainbox
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: Web-server and API to access the curated set of AI-deciders, packaged as containers
|
|
5
|
+
Author-email: Yuri Okulovsky <yuri.okulovsky@gmail.com>
|
|
6
|
+
License: GPLv3
|
|
7
|
+
Project-URL: repository, https://github.com/okulovsky/kaia/tree/main/brainbox
|
|
8
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Intended Audience :: Information Technology
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Classifier: Development Status :: 4 - Beta
|
|
18
|
+
Requires-Python: <4.0,>=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: yo_fluq_ds
|
|
21
|
+
Requires-Dist: flask
|
|
22
|
+
Requires-Dist: requests
|
|
23
|
+
Requires-Dist: sqlalchemy
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: tox; extra == "dev"
|
|
26
|
+
Requires-Dist: tox-conda; extra == "dev"
|
|
27
|
+
Requires-Dist: twine; extra == "dev"
|
|
28
|
+
|
|
29
|
+
# Introduction
|
|
30
|
+
|
|
31
|
+
BrainBox provides easy HTTP access to a set of curated Docker containers
|
|
32
|
+
with AI-systems processing images, texts and sounds.
|
|
33
|
+
It comes with API endpoints to build the container and download basic models,
|
|
34
|
+
self-tests and documentation, as well as unified access to all the models.
|
|
35
|
+
The main use case is fast prototyping of small AI-driven products:
|
|
36
|
+
managing chats in messengers, self-hosted voice assistants,
|
|
37
|
+
media processing (translation, covering images), etc.
|
|
38
|
+
BrainBox is open-source and self-hosted, so no external APIs are needed;
|
|
39
|
+
GPU is recommended for some, but not all, models.
|
|
40
|
+
|
|
41
|
+
BrainBox is not a production-ready solution. **Do not use it** in production environment,
|
|
42
|
+
since it doesn't have any security features, isn't really compatible with high and even
|
|
43
|
+
moderate load, and at the same time may have a big impact on the system's resources.
|
|
44
|
+
The suggested use of BrainBox is your own home machine,
|
|
45
|
+
where the security is provided on the network, not application, level.
|
|
46
|
+
Ideally, this machine would have a decent GPU unit: many AI-systems do not require GPU,
|
|
47
|
+
but some (the most interesting ones, of course) are practically useless without it,
|
|
48
|
+
and few won't even run.
|
|
49
|
+
|
|
50
|
+
## Included deciders
|
|
51
|
+
|
|
52
|
+
They are many.
|
|
53
|
+
At some point, BrainBox will have a comprehensive documentation for each of them, but we're not there yet.
|
|
54
|
+
Important deciders are:
|
|
55
|
+
* For TTS, text-to-speech:
|
|
56
|
+
* [OpenTTS](https://github.com/synesthesiam/opentts) provides a decent baseline for english language with VITS model
|
|
57
|
+
* [CoquiTTS](https://github.com/coqui-ai/TTS) is a framework supporting many different models.
|
|
58
|
+
That includes VITS as well as YourTTS, and, of course, their own XTTS, that can do a good voice cloning.
|
|
59
|
+
* [TortoiseTTS](https://github.com/neonbjb/tortoise-tts) is, in my opinion, still the best in terms of quality.
|
|
60
|
+
It is very slow, but not as slow as it used to be.
|
|
61
|
+
* For STT, speech-to-text, and other voice analysis:
|
|
62
|
+
* [Whisper](https://github.com/WhisperSpeech/WhisperSpeech) is a de-facto standard.
|
|
63
|
+
* [Kaldi](https://kaldi-asr.org/), which we use via its implementation in [Rhasspy](https://rhasspy.readthedocs.io/en/latest/),
|
|
64
|
+
provides much faster and accurate result _over the closed grammar and vocabulary_.
|
|
65
|
+
It is not really a general solution for STT, but is perfect for home assistants.
|
|
66
|
+
* [Resemblyzer](https://github.com/resemble-ai/Resemblyzer) does speaker identification.
|
|
67
|
+
* For text processing:
|
|
68
|
+
* [Ollama](https://ollama.com/), a de-facto standard for LLM management, is supported.
|
|
69
|
+
* For image generation and processing:
|
|
70
|
+
* [ComfyUI](https://github.com/comfyanonymous/ComfyUI), a standard for image generation, is supported
|
|
71
|
+
* [YOLO](https://docs.ultralytics.com/) is supported for object detection.
|
|
72
|
+
|
|
73
|
+
... And more are coming.
|
|
74
|
+
Once you install BrainBox, you will have all these AIs privately and free of charge on your machine,
|
|
75
|
+
accessible via user-friendly Python API, or by simple HTTP requests!
|
|
76
|
+
|
|
77
|
+
# Installation
|
|
78
|
+
|
|
79
|
+
## Docker
|
|
80
|
+
|
|
81
|
+
You need [Docker](https://docs.docker.com/engine/install/) installed in your system,
|
|
82
|
+
and the access granted to the current user to run `docker` from command line without elevated privileges.
|
|
83
|
+
The command
|
|
84
|
+
|
|
85
|
+
```commandline
|
|
86
|
+
docker run hello-world
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
should work successfully and produce the text starting with "Hello from Docker!"
|
|
90
|
+
|
|
91
|
+
## Python environment
|
|
92
|
+
|
|
93
|
+
[Anaconda](https://www.anaconda.com/download/success) is recommended to manage Python's
|
|
94
|
+
environments. Create an environment for e.g. Python 3.11 (BrainBox is tested with 3.10-3.13 Python versions):
|
|
95
|
+
|
|
96
|
+
```commandline
|
|
97
|
+
conda create --name brainbox python==3.11
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Then, activate the environment
|
|
101
|
+
|
|
102
|
+
```commandline
|
|
103
|
+
conda activate brainbox
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## BrainBox
|
|
107
|
+
|
|
108
|
+
Install the brainbox
|
|
109
|
+
|
|
110
|
+
```commandline
|
|
111
|
+
pip install kaia-brainbox
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Run the brainbox
|
|
115
|
+
|
|
116
|
+
```commandline
|
|
117
|
+
python -m brainbox.run --folder <where_all_files_will_be_stored>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# Python's API
|
|
123
|
+
|
|
124
|
+
This is the simplest way to access the BrainBox functionality.
|
|
125
|
+
To use it, simply install BrainBox to your project with `pip install brainbox`
|
|
126
|
+
|
|
127
|
+
## Basic techniques
|
|
128
|
+
|
|
129
|
+
These are the operations you use for all the deciders all the time you work with BrainBox.
|
|
130
|
+
|
|
131
|
+
To execute the following code, you need to run BrainBox and keep it running.
|
|
132
|
+
|
|
133
|
+
Note, that the code below is also part of the module tests and is located at `/tests/test_readme/`.
|
|
134
|
+
In this documentation, regions from this test are copy-pasted, along with asserts for better understanding of returned values,
|
|
135
|
+
so `test_case` represents a `unittest` TestCase instance.
|
|
136
|
+
|
|
137
|
+
### Create an API object
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from brainbox import BrainBox
|
|
141
|
+
|
|
142
|
+
api = BrainBox.Api("127.0.0.1:8090")
|
|
143
|
+
api.wait(1)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This will create an API object. `wait` will try to connect to the endpoint
|
|
147
|
+
for 1 second, and raises if unsuccessful.
|
|
148
|
+
|
|
149
|
+
### Install the decider
|
|
150
|
+
|
|
151
|
+
We have a `Boilerplate` decider, that doesn't do anything useful,
|
|
152
|
+
but accumulates all the features BrainBox has for deciders.
|
|
153
|
+
Let's install the decider:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
|
|
157
|
+
report = api.controller_api.install(Boilerplate)
|
|
158
|
+
test_case.assertIsNotNone(report)
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Note that the container is not pulled, but build on your machine,
|
|
163
|
+
and this is also the case for other deciders.
|
|
164
|
+
This is resource-intensive, in terms of bandwidth and time,
|
|
165
|
+
but allows you to modify the containers quickly
|
|
166
|
+
if you require some model's functionality that wasn't implemented.
|
|
167
|
+
Also it allows BrainBox to work completely independently,
|
|
168
|
+
with the source code only, without reliance to the external
|
|
169
|
+
docker repositories; and finally, it's much easier to check what
|
|
170
|
+
these containers are doing.
|
|
171
|
+
|
|
172
|
+
Returned `report` can largely be ignored, it's only needed for
|
|
173
|
+
GUI purposes.
|
|
174
|
+
|
|
175
|
+
### Run a self-test
|
|
176
|
+
|
|
177
|
+
The self-tests for the deciders run the most important endpoints,
|
|
178
|
+
and ensure their correct work.
|
|
179
|
+
Also, they provide a report where you can see the inputs and outputs
|
|
180
|
+
for the endpoint, so it is documentation of some sort.
|
|
181
|
+
This report can be viewed as an HTML page.
|
|
182
|
+
|
|
183
|
+
This will run a self-test and opens the result in the web-browser.
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
|
|
187
|
+
import requests, webbrowser, tempfile
|
|
188
|
+
from pathlib import Path
|
|
189
|
+
|
|
190
|
+
api.controller_api.self_test(Boilerplate)
|
|
191
|
+
self_test_report = requests.get(f'http://{api.address}/html/controllers/self_test_report/Boilerplate').text
|
|
192
|
+
test_case.assertIsInstance(self_test_report, str)
|
|
193
|
+
|
|
194
|
+
test_case_test_path = Path(tempfile.gettempdir()) / 'test_report.html'
|
|
195
|
+
with open(test_case_test_path, 'w') as file:
|
|
196
|
+
file.write(self_test_report)
|
|
197
|
+
|
|
198
|
+
# webbrowser.open('file://'+str(test_case_test_path))
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
While self-test reports provide some understanding of the endpoints,
|
|
203
|
+
I recommend reading the self-tests code: all the endpoints are called
|
|
204
|
+
in the same way you will call them from your Python code.
|
|
205
|
+
Self-tests, building containers and other container-related things
|
|
206
|
+
are performed by `Controller` classes. They are usually located
|
|
207
|
+
within deciders classes, e.g. `Boilerplate.Controller`
|
|
208
|
+
|
|
209
|
+
### Call an endpoint
|
|
210
|
+
|
|
211
|
+
This will execute the method Boilerplate::json on the server side.
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
|
|
215
|
+
result = api.execute(BrainBox.Task.call(Boilerplate).json("Hello"))
|
|
216
|
+
test_case.assertDictEqual(
|
|
217
|
+
{
|
|
218
|
+
'argument': 'Hello',
|
|
219
|
+
'model': 'no_parameter',
|
|
220
|
+
'setting': 'default_setting'
|
|
221
|
+
},
|
|
222
|
+
result
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
The BrainBox will run the container for the Boilerplate decider.
|
|
228
|
+
This container has a web-server inside, and Boilerplate::json
|
|
229
|
+
connects to this web-server and performs the required operation.
|
|
230
|
+
The result (in this case, `dict`) is then returned to the caller.
|
|
231
|
+
As you see, `argument` equals to the argument the code provides.
|
|
232
|
+
|
|
233
|
+
BrainBox is smart and tries to minimize the containers' runs.
|
|
234
|
+
If several tasks for same decider have arrived,
|
|
235
|
+
this decider will be set up, and then all these tasks will be executed
|
|
236
|
+
before the tasks for other deciders.
|
|
237
|
+
|
|
238
|
+
### Call an enpoint with a parameter
|
|
239
|
+
|
|
240
|
+
Few deciders have parameters: a string argument that will be fed to the container
|
|
241
|
+
on the start, and may modify its behaviour. It's sometimes required
|
|
242
|
+
when you don't build container from scratch, but use a ready container,
|
|
243
|
+
which requires you to load the model on the startup, and in this case,
|
|
244
|
+
`parameter` is this model's name.
|
|
245
|
+
|
|
246
|
+
To pass the parameter, simply add it to `call` function:
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
|
|
250
|
+
result = api.execute(BrainBox.Task.call(Boilerplate, "parameter").json("Hello"))
|
|
251
|
+
test_case.assertDictEqual(
|
|
252
|
+
{
|
|
253
|
+
'argument': 'Hello',
|
|
254
|
+
'model': 'parameter',
|
|
255
|
+
'setting': 'default_setting'
|
|
256
|
+
},
|
|
257
|
+
result
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
As you can see, the `model` field is now set to `parameter`.
|
|
263
|
+
|
|
264
|
+
Most of the deciders do not have the parameter and load models dynamically, so normally you write
|
|
265
|
+
`BrainBoxTask.call(DeciderClass).method(...)`
|
|
266
|
+
|
|
267
|
+
Please ignore the `setting` field.
|
|
268
|
+
There is a possibility to adjust settings to the controllers,
|
|
269
|
+
such as the port the internal web-server will be assigned for,
|
|
270
|
+
or the list of models the controllers need to download,
|
|
271
|
+
but so far there was never a necessity to adjust them manually.
|
|
272
|
+
They are only used with the default values.
|
|
273
|
+
|
|
274
|
+
### Download files, produced by deciders
|
|
275
|
+
|
|
276
|
+
Many BrainBox deciders return files with generated images or sounds.
|
|
277
|
+
In order not to overload the BrainBox database with all these
|
|
278
|
+
gigabytes, the files are stored in the cache folder,
|
|
279
|
+
and only files' names are returned.
|
|
280
|
+
|
|
281
|
+
```python
|
|
282
|
+
|
|
283
|
+
filename = api.execute(BrainBox.Task.call(Boilerplate).file("Hello, file!"))
|
|
284
|
+
test_case.assertIsInstance(filename, str)
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
You may open this file with `api.open_file` method, which returns `File`
|
|
289
|
+
instance, reading the content of the file on the fly.
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
|
|
293
|
+
from brainbox import File
|
|
294
|
+
import json
|
|
295
|
+
|
|
296
|
+
file = api.open_file(filename)
|
|
297
|
+
test_case.assertIsInstance(file, File)
|
|
298
|
+
test_case.assertDictEqual(
|
|
299
|
+
{
|
|
300
|
+
'argument': 'Hello, file!',
|
|
301
|
+
'model': 'no_parameter',
|
|
302
|
+
'setting': 'default_setting'
|
|
303
|
+
},
|
|
304
|
+
json.loads(file.content)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
If you don't want to open the file, only download it on the disk:
|
|
310
|
+
|
|
311
|
+
```python
|
|
312
|
+
from pathlib import Path
|
|
313
|
+
|
|
314
|
+
path = api.download(filename)
|
|
315
|
+
test_case.assertIsInstance(path, Path)
|
|
316
|
+
with open(path, 'r') as stream:
|
|
317
|
+
test_case.assertDictEqual(
|
|
318
|
+
{
|
|
319
|
+
'argument': 'Hello, file!',
|
|
320
|
+
'model': 'no_parameter',
|
|
321
|
+
'setting': 'default_setting'
|
|
322
|
+
},
|
|
323
|
+
json.load(stream)
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
which simply downloads the file on the disk to the given location
|
|
329
|
+
(by default, in the API's cache folder), and returns the full path to file.
|
|
330
|
+
You may specify the location and the flag to redownload the file even
|
|
331
|
+
if it was already downloaded.
|
|
332
|
+
|
|
333
|
+
### Upload files, required by deciders
|
|
334
|
+
|
|
335
|
+
Some deciders, especially speech-to-text or image analysis,
|
|
336
|
+
use files as inputs. You may feed them directly in the call:
|
|
337
|
+
|
|
338
|
+
```python
|
|
339
|
+
from brainbox import File
|
|
340
|
+
|
|
341
|
+
file = File('hello.txt', "Hello, world!")
|
|
342
|
+
test_case.assertEqual(file.name, 'hello.txt')
|
|
343
|
+
test_case.assertEqual(file.content, b'Hello, world!')
|
|
344
|
+
|
|
345
|
+
length = api.execute(BrainBox.Task.call(Boilerplate).file_length(file))
|
|
346
|
+
test_case.assertEqual(length, 13)
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
However, that has the potential to overload the database as well,
|
|
351
|
+
and should be avoided.
|
|
352
|
+
|
|
353
|
+
If you run BrainBox server at the machine you're running `api`,
|
|
354
|
+
you may pass the path of the file:
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
|
|
358
|
+
import tempfile
|
|
359
|
+
from pathlib import Path
|
|
360
|
+
|
|
361
|
+
path = file.write(tempfile.gettempdir())
|
|
362
|
+
test_case.assertIsInstance(path, Path)
|
|
363
|
+
|
|
364
|
+
length = api.execute(BrainBox.Task.call(Boilerplate).file_length(path))
|
|
365
|
+
test_case.assertEqual(length, 13)
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
This solution is dirty as it won't work with a remote BrainBox,
|
|
370
|
+
and would force you to rewrite your codebase in case of such change.
|
|
371
|
+
|
|
372
|
+
To avoid this, you may choose to upload the file to the BrainBox
|
|
373
|
+
cache folder instead:
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
|
|
377
|
+
api.upload(file.name, file)
|
|
378
|
+
length = api.execute(BrainBox.Task.call(Boilerplate).file_length(file.name))
|
|
379
|
+
test_case.assertEqual(length, 13)
|
|
380
|
+
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Sometimes, files are required to have specific names, or some
|
|
384
|
+
recoding. In these cases, deciders usually have static methods
|
|
385
|
+
that incapsulate these procedures in Prerequisites:
|
|
386
|
+
|
|
387
|
+
```python
|
|
388
|
+
upload_prerequisite = Boilerplate.file_upload(file)
|
|
389
|
+
upload_prerequisite.execute(api)
|
|
390
|
+
length = api.execute(BrainBox.Task.call(Boilerplate).file_length(file.name))
|
|
391
|
+
test_case.assertEqual(length, 13)
|
|
392
|
+
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Advanced techniques
|
|
396
|
+
|
|
397
|
+
### Browse the resources
|
|
398
|
+
|
|
399
|
+
Many deciders have _resources_: files, typically model files, that are passed to the containers and used for inference.
|
|
400
|
+
It is impractical to store them inside containers, and so BrainBox stores them in the host's file system:
|
|
401
|
+
each decider has its own resource folder, which is mounted to the container.
|
|
402
|
+
|
|
403
|
+
Aside from models, the training data may be stored in resources instead of file cache, as training data
|
|
404
|
+
are easier to organize with folder structure and predictable filenames.
|
|
405
|
+
|
|
406
|
+
This endpoint demonstrates that the server indeed has an access to the resources:
|
|
407
|
+
Boilerplate reads them and returns the dictionary of keys set to filenames,
|
|
408
|
+
and values set to file content.
|
|
409
|
+
These resources are created by Boilerplate controller as a part of installation procedure.
|
|
410
|
+
|
|
411
|
+
```python
|
|
412
|
+
resources = api.execute(BrainBox.Task.call(Boilerplate).resources())
|
|
413
|
+
test_case.assertDictEqual(
|
|
414
|
+
{'nested/resource': 'Boilerplate nested resource', 'resource': 'Boilerplate resource'},
|
|
415
|
+
resources
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
However, a uniform access to all the resources is provided by API, e.g. to list all the resources:
|
|
421
|
+
|
|
422
|
+
```python
|
|
423
|
+
|
|
424
|
+
resources = api.controller_api.list_resources(Boilerplate, '/')
|
|
425
|
+
test_case.assertListEqual(
|
|
426
|
+
['resource', 'nested/resource'],
|
|
427
|
+
resources
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Download a custom model
|
|
433
|
+
|
|
434
|
+
Many deciders can run with different models, and these models need to be downloaded.
|
|
435
|
+
All the deciders load some models at the installation time to allow self-test to run.
|
|
436
|
+
However, more models are usually needed.
|
|
437
|
+
|
|
438
|
+
Sometimes the containers are able to download these models themselves,
|
|
439
|
+
but often enough the models need to be downloaded separately.
|
|
440
|
+
|
|
441
|
+
This action can be triggered via `api`:
|
|
442
|
+
|
|
443
|
+
```python
|
|
444
|
+
|
|
445
|
+
api.controller_api.download_models(Boilerplate, [Boilerplate.Model('google', 'http://www.google.com')])
|
|
446
|
+
resources = api.controller_api.list_resources(Boilerplate, '/models')
|
|
447
|
+
test_case.assertListEqual(['models/google'], resources)
|
|
448
|
+
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Build a workflow from tasks
|
|
452
|
+
|
|
453
|
+
The output of the tasks can serve as an input to other tasks:
|
|
454
|
+
|
|
455
|
+
```python
|
|
456
|
+
task1 = BrainBox.Task.call(Boilerplate).json("Hello")
|
|
457
|
+
task2 = BrainBox.Task.call(Boilerplate).json(task1)
|
|
458
|
+
result = api.execute([task1, task2])
|
|
459
|
+
test_case.assertDictEqual(result[0], result[1]['argument'])
|
|
460
|
+
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
In this case, the `task1` will be executed before `task2` and the output of `task1` will be used
|
|
464
|
+
as an argument for `task2` method.
|
|
465
|
+
|
|
466
|
+
### Collect the outputs of many tasks
|
|
467
|
+
|
|
468
|
+
One particularly important use case of the dependent tasks is when
|
|
469
|
+
several tasks are run, each associated with some __tags__ describing a task,
|
|
470
|
+
and then the outputs of all tasks are collected together and returned as a single entity.
|
|
471
|
+
|
|
472
|
+
`Collector` does just this. Declaring collector tasks in a raw form is very cumbersome,
|
|
473
|
+
and we actually use helpers to do this,
|
|
474
|
+
however, it helps to see what's going on under the hood.
|
|
475
|
+
|
|
476
|
+
```python
|
|
477
|
+
from brainbox.deciders import Collector
|
|
478
|
+
from brainbox import BrainBoxCombinedTask
|
|
479
|
+
|
|
480
|
+
id1 = 'id_1'
|
|
481
|
+
id2 = 'id_2'
|
|
482
|
+
task1 = BrainBox.Task.call(Boilerplate).json(0).to_task(id=id1)
|
|
483
|
+
task2 = BrainBox.Task.call(Boilerplate).json(1).to_task(id=id2)
|
|
484
|
+
collector = BrainBox.Task.call(Collector).to_array(
|
|
485
|
+
tags = {id1: dict(index=0), id2: dict(index=1)},
|
|
486
|
+
** {
|
|
487
|
+
id1: task1,
|
|
488
|
+
id2: task2
|
|
489
|
+
}
|
|
490
|
+
)
|
|
491
|
+
pack = BrainBoxCombinedTask(
|
|
492
|
+
resulting_task = collector,
|
|
493
|
+
intermediate_tasks = (task1, task2)
|
|
494
|
+
)
|
|
495
|
+
array = api.execute(pack)
|
|
496
|
+
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
We can shorten this significantly with `Collector.TaskBuilder`:
|
|
500
|
+
|
|
501
|
+
```python
|
|
502
|
+
|
|
503
|
+
builder = Collector.TaskBuilder()
|
|
504
|
+
for i in range(10):
|
|
505
|
+
builder.append(task=BrainBox.Task.call(Boilerplate).json(i), tags=dict(index=i))
|
|
506
|
+
pack = builder.to_collector_pack('to_array')
|
|
507
|
+
array = api.execute(pack)
|
|
508
|
+
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### Collect the files from many tasks
|
|
512
|
+
|
|
513
|
+
One problem remains: if deciders return files, these files won't be collected.
|
|
514
|
+
To solve it, MediaLibrary structure is used. Essentially it's a zip-file
|
|
515
|
+
that contains all the outputs as well as tags.
|
|
516
|
+
|
|
517
|
+
```python
|
|
518
|
+
from brainbox import MediaLibrary
|
|
519
|
+
from brainbox.deciders import Collector
|
|
520
|
+
import json
|
|
521
|
+
|
|
522
|
+
builder = Collector.TaskBuilder()
|
|
523
|
+
for i in range(10):
|
|
524
|
+
builder.append(task=BrainBox.Task.call(Boilerplate).file(i), tags=dict(index=i))
|
|
525
|
+
pack = builder.to_collector_pack('to_media_library')
|
|
526
|
+
path = api.download(api.execute(pack))
|
|
527
|
+
ml = MediaLibrary.read(path)
|
|
528
|
+
for record in ml.records:
|
|
529
|
+
content = record.get_content()
|
|
530
|
+
tags = record.tags
|
|
531
|
+
test_case.assertEqual(tags['index'], json.loads(content)['argument'])
|
|
532
|
+
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
# Use it without Python
|
|
536
|
+
|
|
537
|
+
All the BrainBox functionality is accessible without Python API, with direct HTTP requests.
|
|
538
|
+
Since Python API actually works over the HTTP requests to BrainBox server,
|
|
539
|
+
and the API calls are translated into HTTP requests automatically with `brainbox.framework.common.marshalling` module,
|
|
540
|
+
I can guarantee that it works.
|
|
541
|
+
However, it is not yet nicely documented.
|
|
542
|
+
|
|
543
|
+
## Manage the controllers
|
|
544
|
+
|
|
545
|
+
Installation, running, stopping and self-testing of deciders is available on
|
|
546
|
+
`http://127.0.0.1:8090/html/controllers/status`.
|
|
547
|
+
The web-page is hopefully self-explanatory.
|
|
548
|
+
|
|
549
|
+
The web-page also allows you to start the container.
|
|
550
|
+
Since most of the containers have web-server inside, you can call the endpoints of these web-servers
|
|
551
|
+
instead of BrainBox.
|
|
552
|
+
These servers, however, are not nicely written, don't have the documentation
|
|
553
|
+
and there is no plan to write this documentation in the future,
|
|
554
|
+
because it's a massive work that will have little sense,
|
|
555
|
+
since BrainBox implements the calls itself.
|
|
556
|
+
|
|
557
|
+
## Run the tasks
|
|
558
|
+
|
|
559
|
+
To run the deciders via BrainBox, we have two endpoints, `/jobs/add` and `/jobs/join`.
|
|
560
|
+
|
|
561
|
+
`jobs/add` accepts a list of dictionaries, each describing one job.
|
|
562
|
+
What we did above with `BrainBox.Task.call(Boilerplate)` was actually a definition of the job with API.
|
|
563
|
+
Job has the following fields:
|
|
564
|
+
|
|
565
|
+
* `id`: a unique string id of the job
|
|
566
|
+
* `decider`: the name of the decider, like `"Boilerlate"` string
|
|
567
|
+
* `method`: the method of decider class we're running. Can be None if the class defines `__call__` method and is therefore callable itself.
|
|
568
|
+
* `decider_parameter`: decider's parameter, usually None
|
|
569
|
+
* `arguments`: arguments of the method as dictionary.
|
|
570
|
+
* `info`: arbitrary data that is associated with the job, but doesn't have any effect on it.
|
|
571
|
+
* `batch`: jobs in e.g. `Collector`'s packs are organized in batches, so in the web-interface it may be seen what percentage
|
|
572
|
+
of this collective job is finished.
|
|
573
|
+
* `dependencies`: a dictionary with keys set to the names of the arguments of the method, and values as id of the dependent tasks.
|
|
574
|
+
If the key starts with `*`, the dependent task will be waited for, but it's value won't be used.
|
|
575
|
+
* `ordering_token`: None or an arbitrary string that helps BrainBox arrange the jobs to minimize the model switching.
|
|
576
|
+
Something like `<larger_model_name>/<smaller_model_name>/<even_smaller_model_name>` is usually sufficient.
|
|
577
|
+
|
|
578
|
+
Simply the list of such dictionaries to the BrainBox server and it will add the tasks to the queue,
|
|
579
|
+
returning the control immediately.
|
|
580
|
+
To block your process until the tasks are finished, use `/jobs/join` endpoint,
|
|
581
|
+
and provide it with the list of `id` of the jobs you want to wait for.
|
|
582
|
+
As a result, `/jobs/join` will return a list of arbitrary objects that correspond to the list of `id`.
|
|
583
|
+
|
|
584
|
+
```python
|
|
585
|
+
import requests
|
|
586
|
+
import uuid
|
|
587
|
+
|
|
588
|
+
address = api.address
|
|
589
|
+
id = str(uuid.uuid4())
|
|
590
|
+
|
|
591
|
+
reply = requests.post(f'http://{address}/jobs/add', json=
|
|
592
|
+
{
|
|
593
|
+
"arguments": {
|
|
594
|
+
"jobs": [
|
|
595
|
+
{
|
|
596
|
+
"id": id,
|
|
597
|
+
"decider": "Boilerplate",
|
|
598
|
+
"method": "json",
|
|
599
|
+
"decider_parameter": None,
|
|
600
|
+
"arguments": {
|
|
601
|
+
"argument": "Hello, HTTP"
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
]
|
|
605
|
+
}
|
|
606
|
+
})
|
|
607
|
+
if reply.status_code != 200:
|
|
608
|
+
raise ValueError(f"Endpoint returned {reply.status_code}\n{reply.json()['error']}")
|
|
609
|
+
|
|
610
|
+
reply = requests.get(f"http://{address}/jobs/join", json=
|
|
611
|
+
{
|
|
612
|
+
"arguments": {
|
|
613
|
+
"ids": [
|
|
614
|
+
id
|
|
615
|
+
]
|
|
616
|
+
}
|
|
617
|
+
})
|
|
618
|
+
|
|
619
|
+
if reply.status_code != 200:
|
|
620
|
+
raise ValueError(f"Endpoint returned {reply.status_code}\n{reply.json()['error']}")
|
|
621
|
+
|
|
622
|
+
result = reply.json()['result'][0]
|
|
623
|
+
test_case.assertDictEqual(
|
|
624
|
+
{
|
|
625
|
+
'argument': 'Hello, HTTP',
|
|
626
|
+
'model': 'no_parameter',
|
|
627
|
+
'setting': 'default_setting'
|
|
628
|
+
},
|
|
629
|
+
result
|
|
630
|
+
)
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
|