bertrend 0.3.20__tar.gz → 0.3.22__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.
- {bertrend-0.3.20 → bertrend-0.3.22}/PKG-INFO +4 -1
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/__init__.py +28 -13
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/i18n.py +22 -15
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/start_summarizer_app.sh +1 -1
- bertrend-0.3.22/bertrend/demos/start_topic_analysis_app.sh +36 -0
- bertrend-0.3.22/bertrend/demos/start_weak_signals_app.sh +36 -0
- bertrend-0.3.22/bertrend/services/scheduling/.dockerignore +52 -0
- bertrend-0.3.22/bertrend/services/scheduling/Docker_setup.md +310 -0
- bertrend-0.3.22/bertrend/services/scheduling/Dockerfile +29 -0
- bertrend-0.3.22/bertrend/services/scheduling/dashboard.html +698 -0
- bertrend-0.3.22/bertrend/services/scheduling/docker-compose.yml +53 -0
- bertrend-0.3.22/bertrend/services/scheduling/job_utils/job_functions.py +54 -0
- bertrend-0.3.22/bertrend/services/scheduling/models/scheduling_models.py +137 -0
- bertrend-0.3.22/bertrend/services/scheduling/requirements.txt +7 -0
- bertrend-0.3.22/bertrend/services/scheduling/routers/info.py +20 -0
- bertrend-0.3.22/bertrend/services/scheduling/routers/scheduling.py +644 -0
- bertrend-0.3.22/bertrend/services/scheduling/scheduling_service.py +22 -0
- bertrend-0.3.22/bertrend/tests/apps/test_bertrend_service.py +293 -0
- bertrend-0.3.22/bertrend/tests/apps/test_models.py +208 -0
- {bertrend-0.3.20/bertrend_apps/tests → bertrend-0.3.22/bertrend/tests/apps}/test_process_new_data.py +27 -19
- bertrend-0.3.22/bertrend/tests/apps/test_routers_bertrend_app.py +285 -0
- bertrend-0.3.22/bertrend/tests/apps/test_routers_info.py +39 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/tests/conftest.py +0 -2
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_temporal_metrics_embedding.py +257 -9
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_topic_metrics.py +0 -2
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_visualizations.py +0 -1
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_agent_utils.py +1 -3
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_article_scoring.py +5 -1
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_newsletter_features.py +5 -0
- bertrend-0.3.22/bertrend/tests/services/scheduling/__init__.py +4 -0
- bertrend-0.3.22/bertrend/tests/services/scheduling/test_scheduling_service.py +256 -0
- bertrend-0.3.22/bertrend/tests/services/summarizer/__init__.py +4 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/summarizer}/test_abstractive_summarizer.py +1 -1
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/summarizer}/test_extractive_summarizer.py +1 -5
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/tests/test_integration.py +43 -50
- bertrend-0.3.22/bertrend/tests/utils/__init__.py +4 -0
- bertrend-0.3.22/bertrend/tests/utils/test_apscheduler_utils.py +578 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/utils}/test_cache_utils.py +1 -1
- bertrend-0.3.22/bertrend/tests/utils/test_crontab_utils.py +454 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/utils}/test_data_loading.py +1 -2
- bertrend-0.3.22/bertrend/tests/utils/test_date_utils.py +169 -0
- bertrend-0.3.22/bertrend/tests/utils/test_mail_utils.py +354 -0
- bertrend-0.3.22/bertrend/tests/utils/test_scheduler_utils.py +220 -0
- bertrend-0.3.22/bertrend/topic_analysis/__init__.py +4 -0
- bertrend-0.3.22/bertrend/trend_analysis/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/__init__.py +36 -0
- bertrend-0.3.22/bertrend_apps/common/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/common/apscheduler_utils.py +321 -0
- bertrend-0.3.22/bertrend_apps/common/crontab_utils.py +187 -0
- bertrend-0.3.22/bertrend_apps/common/date_utils.py +25 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/common/mail_utils.py +6 -2
- bertrend-0.3.22/bertrend_apps/common/scheduler_utils.py +153 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/__init__.py +2 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/__main__.py +24 -115
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/arxiv_provider.py +2 -2
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/data_provider.py +6 -2
- bertrend-0.3.22/bertrend_apps/data_provider/data_provider_utils.py +172 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/newscatcher_provider.py +1 -1
- bertrend-0.3.22/bertrend_apps/exploration/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/exploration/curebot/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/exploration/start_apps.sh +36 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/install_feeds_and_newsletters.py +3 -3
- bertrend-0.3.22/bertrend_apps/newsletters/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/newsletters/__main__.py +48 -0
- bertrend-0.3.22/bertrend_apps/newsletters/newsletter_generation.py +191 -0
- bertrend-0.3.22/bertrend_apps/newsletters/utils.py +84 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/__init__.py +1 -2
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/app.py +2 -2
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/automated_report_generation.py +33 -16
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/dashboard_analysis.py +1 -4
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/dashboard_common.py +1 -1
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/dashboard_comparative.py +67 -44
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/dashboard_signals.py +1 -1
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/feeds_config.py +21 -21
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/feeds_data.py +1 -1
- bertrend-0.3.22/bertrend_apps/prospective_demo/i18n.py +40 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/i18n_translations.py +88 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/models_info.py +52 -144
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/process_new_data.py +156 -60
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/report_generation.py +7 -41
- bertrend-0.3.22/bertrend_apps/prospective_demo/report_generation_utils.py +46 -0
- bertrend-0.3.22/bertrend_apps/prospective_demo/start_demo.sh +36 -0
- bertrend-0.3.22/bertrend_apps/services/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/services/bertrend_service.py +19 -0
- bertrend-0.3.22/bertrend_apps/services/config/default_config.toml +4 -0
- bertrend-0.3.22/bertrend_apps/services/config/settings.py +33 -0
- bertrend-0.3.22/bertrend_apps/services/models/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/services/models/bertrend_app_models.py +54 -0
- bertrend-0.3.22/bertrend_apps/services/models/data_provider_models.py +66 -0
- bertrend-0.3.22/bertrend_apps/services/models/newsletters_models.py +34 -0
- bertrend-0.3.22/bertrend_apps/services/routers/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/services/routers/bertrend_app.py +140 -0
- bertrend-0.3.22/bertrend_apps/services/routers/data_provider.py +157 -0
- bertrend-0.3.22/bertrend_apps/services/routers/info.py +29 -0
- bertrend-0.3.22/bertrend_apps/services/routers/newsletters.py +66 -0
- bertrend-0.3.22/bertrend_apps/services/start.py +24 -0
- bertrend-0.3.22/bertrend_apps/services/status.py +30 -0
- bertrend-0.3.22/bertrend_apps/services/stop.py +14 -0
- bertrend-0.3.22/bertrend_apps/services/utils/__init__.py +4 -0
- bertrend-0.3.22/bertrend_apps/services/utils/logging_utils.py +30 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/pyproject.toml +4 -1
- bertrend-0.3.20/bertrend/demos/start_topic_analysis_app.sh +0 -14
- bertrend-0.3.20/bertrend/demos/start_weak_signals_app.sh +0 -14
- bertrend-0.3.20/bertrend/tests/test_mail_utils.py +0 -468
- bertrend-0.3.20/bertrend_apps/common/crontab_utils.py +0 -141
- bertrend-0.3.20/bertrend_apps/newsletters/__main__.py +0 -293
- bertrend-0.3.20/bertrend_apps/prospective_demo/start_demo.sh +0 -16
- bertrend-0.3.20/bertrend_apps/start_apps.sh +0 -15
- {bertrend-0.3.20 → bertrend-0.3.22}/AUTHORS.txt +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/LICENSE.md +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/README.md +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/BERTopicModel.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/BERTrend.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/article_scoring/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/article_scoring/article_scoring.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/article_scoring/prompts.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/article_scoring/scoring_agent.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/config/bertopic_default_config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/config/bertrend_default_config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/config/parameters.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/config/services_default_config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/data_loading_component.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/embed_documents_component.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/i18n_translations.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/icons.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/parameters_component.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/state_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/streamlit_components/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/streamlit_components/clickable_df_component.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/streamlit_components/input_with_pills_component.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/summarization/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/summarization/summarizer_app.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/.streamlit/config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/app.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/app_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/explore_topics.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/newsletters_generation.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/temporal_visualizations.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/topic_visualizations.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/training_page.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/i18n_translations.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/.streamlit/config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/app.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/i18n_translations.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/visualizations_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/agent_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter.css +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter_features.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter_model.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter_outlook_template.html +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter_template.html +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/openai_client.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/prompts.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/metrics/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/metrics/temporal_metrics_embedding.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/metrics/topic_metrics.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/resources/common_ngrams.json +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/resources/stopwords-en.json +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/resources/stopwords-fr.json +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/resources/stopwords-rte.json +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/authentication.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/cert.pem +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_client.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/README.md +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/bertrend_client_registry.json +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/config/default_config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/config/settings.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/main.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/models.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/requirements.txt +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/routers/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/routers/authentication.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/routers/embeddings.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/routers/info.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/security.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/start.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/status.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/stop.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_service.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/key.pem +0 -0
- {bertrend-0.3.20/bertrend/services/summary → bertrend-0.3.22/bertrend/services/scheduling}/__init__.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/services/scheduling/job_utils}/__init__.py +0 -0
- {bertrend-0.3.20/bertrend/topic_analysis → bertrend-0.3.22/bertrend/services/scheduling/models}/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summarizer.py +0 -0
- {bertrend-0.3.20/bertrend/trend_analysis → bertrend-0.3.22/bertrend/services/summary}/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/abstractive_summarizer.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/chatgpt_summarizer.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/extractive_summarizer.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/lexrank.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/prompts.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/tests/README_integration_tests.md +0 -0
- {bertrend-0.3.20/bertrend_apps → bertrend-0.3.22/bertrend/tests}/__init__.py +0 -0
- {bertrend-0.3.20/bertrend_apps/common → bertrend-0.3.22/bertrend/tests/apps}/__init__.py +0 -0
- {bertrend-0.3.20/bertrend_apps/exploration → bertrend-0.3.22/bertrend/tests/core}/__init__.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_bertrend.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_data_structure.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_representative_docs.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_topic_description.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_topic_model.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_trend_analysis_data_structure.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_trend_analysis_prompts.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_trend_analysis_visualizations.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_trend_analysis_weak_signals.py +0 -0
- {bertrend-0.3.20/bertrend_apps/exploration/curebot → bertrend-0.3.22/bertrend/tests/llm}/__init__.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_article_scoring_models.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_newsletter_model.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_openai_client.py +0 -0
- {bertrend-0.3.20/bertrend_apps/newsletters → bertrend-0.3.22/bertrend/tests/services}/__init__.py +0 -0
- {bertrend-0.3.20/bertrend_apps/tests → bertrend-0.3.22/bertrend/tests/services/embedding}/__init__.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/embedding}/test_embedding_client.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/summarizer}/test_chatgpt_summarizer.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/summarizer}/test_summarizer.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/tests/test_installation.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/utils}/test_config_utils.py +0 -0
- {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/utils}/test_utils_init.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/data_structure.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/prompts.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/representative_docs.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/topic_description.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/visualizations.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/data_structure.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/prompts.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/signal_llm_template_en.html +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/signal_llm_template_fr.html +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/visualizations.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/weak_signals.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/utils/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/utils/cache_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/utils/config_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/utils/data_loading.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/arxiv_feed.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/decarbonation_feed.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/llm_en_feed.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/llm_feed.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/nlp_feed.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/rte_feed.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/arxiv_newsletter_from_last.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/decarbonation_newsletter_from_last.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/decarbonation_newsletter_from_scratch.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/llm_en_newsletter_from_last.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/llm_newsletter_from_last.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/nlp_newsletter_from_last.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/rte_newsletter_from_last.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/rte_newsletter_from_scratch.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/atom_feed_provider.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/bing_news_provider.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/google_news_provider.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/rss_feed_provider.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/.streamlit/config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/app.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/app_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/import_extraction_article.ipynb +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/prompts.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/start_newsletter_generator.sh +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/tabs/tab1.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/tabs/tab2.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/tabs/tab3.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/dataviz/Main_page.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/dataviz/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/dataviz/pages/1_Data_feeds.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/entity_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/__init__.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/common_factory.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/dbpedia.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/nlp.config +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/utils.py +0 -0
- {bertrend-0.3.20/bertrend_apps → bertrend-0.3.22/bertrend_apps/exploration}/stop_apps.sh +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/.streamlit/config.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/.streamlit/secrets.toml +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/authentication.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/data_model.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/detailed_report_template.html +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/docs/automated_report_generation.md +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/feeds_common.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/llm_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/perf_utils.py +0 -0
- {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bertrend
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.22
|
|
4
4
|
Summary: BERTrend analyses topic evolution over time using state-of-the-art transformer models: topic modelling and LLM
|
|
5
5
|
License: LICENSE.md
|
|
6
6
|
License-File: AUTHORS.txt
|
|
@@ -13,8 +13,10 @@ Maintainer-email: jerome.picault@rte-france.com
|
|
|
13
13
|
Requires-Python: >=3.12,<4.0
|
|
14
14
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
15
|
Provides-Extra: apps
|
|
16
|
+
Requires-Dist: APScheduler (>=3.11.0)
|
|
16
17
|
Requires-Dist: PyJWT (>=2.10.1)
|
|
17
18
|
Requires-Dist: Pyqtree (==1.0.0)
|
|
19
|
+
Requires-Dist: SQLAlchemy (>=2.0.40)
|
|
18
20
|
Requires-Dist: arxiv (>=2.2.0) ; extra == "apps"
|
|
19
21
|
Requires-Dist: bertopic (==0.16.2)
|
|
20
22
|
Requires-Dist: black (>=24.10.0)
|
|
@@ -24,6 +26,7 @@ Requires-Dist: dask (==2024.12.0)
|
|
|
24
26
|
Requires-Dist: datamapplot (==0.3.0)
|
|
25
27
|
Requires-Dist: dateparser (>=1.2.0)
|
|
26
28
|
Requires-Dist: dill (>=0.4.0)
|
|
29
|
+
Requires-Dist: fastapi (>=0.120.0)
|
|
27
30
|
Requires-Dist: feedparser (>=6.0.11) ; extra == "apps"
|
|
28
31
|
Requires-Dist: gensim (>=4.3.3)
|
|
29
32
|
Requires-Dist: google-api-python-client (>=2.148.0) ; extra == "apps"
|
|
@@ -3,20 +3,39 @@
|
|
|
3
3
|
# SPDX-License-Identifier: MPL-2.0
|
|
4
4
|
# This file is part of BERTrend.
|
|
5
5
|
import os
|
|
6
|
+
import sys
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
|
|
8
9
|
from loguru import logger
|
|
9
10
|
|
|
11
|
+
|
|
12
|
+
# Global flag to track initialization
|
|
13
|
+
_initialized = False
|
|
14
|
+
|
|
10
15
|
# Auto-load .env if python-dotenv is available
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
if not _initialized:
|
|
17
|
+
try:
|
|
18
|
+
from dotenv import load_dotenv # type: ignore
|
|
19
|
+
|
|
20
|
+
if load_dotenv(override=True):
|
|
21
|
+
logger.info("Loaded .env file")
|
|
22
|
+
else:
|
|
23
|
+
logger.warning("Failed to load .env file")
|
|
24
|
+
|
|
25
|
+
except Exception:
|
|
26
|
+
pass
|
|
13
27
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
# First, remove the default handler (Loguru always adds one by default)
|
|
29
|
+
logger.remove()
|
|
30
|
+
|
|
31
|
+
# Add back a colorized stdout sink
|
|
32
|
+
logger.add(
|
|
33
|
+
sys.stdout,
|
|
34
|
+
colorize=True,
|
|
35
|
+
format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
_initialized = True
|
|
20
39
|
|
|
21
40
|
from bertrend.utils.config_utils import load_toml_config
|
|
22
41
|
|
|
@@ -43,11 +62,7 @@ LLM_CONFIG = SERVICES_CONFIG["llm_service"]
|
|
|
43
62
|
BEST_CUDA_DEVICE = r"\`nvidia-smi --query-gpu=index,memory.used --format=csv,nounits | tail -n +2 | sort -t',' -k2 -n | head -n 1 | cut -d',' -f1\`"
|
|
44
63
|
|
|
45
64
|
BERTREND_BASE_DIR = os.getenv("BERTREND_BASE_DIR", None)
|
|
46
|
-
BASE_PATH = (
|
|
47
|
-
Path(BERTREND_BASE_DIR)
|
|
48
|
-
if BERTREND_BASE_DIR
|
|
49
|
-
else Path(__file__).parent.parent.parent
|
|
50
|
-
)
|
|
65
|
+
BASE_PATH = Path(BERTREND_BASE_DIR) if BERTREND_BASE_DIR else Path.home() / ".bertrend"
|
|
51
66
|
|
|
52
67
|
# Base dirs
|
|
53
68
|
DATA_PATH = BASE_PATH / "data"
|
|
@@ -8,12 +8,10 @@ Provides functionality for translating text between French and English.
|
|
|
8
8
|
# SPDX-License-Identifier: MPL-2.0
|
|
9
9
|
# This file is part of BERTrend.
|
|
10
10
|
|
|
11
|
-
import streamlit as st
|
|
12
11
|
from typing import Optional
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
)
|
|
13
|
+
import streamlit as st
|
|
14
|
+
|
|
17
15
|
from bertrend.demos.topic_analysis.i18n_translations import (
|
|
18
16
|
TRANSLATIONS as TOPIC_ANALYSIS_TRANSLATIONS,
|
|
19
17
|
)
|
|
@@ -26,9 +24,8 @@ from bertrend.demos.weak_signals.i18n_translations import (
|
|
|
26
24
|
|
|
27
25
|
# Merge all translations
|
|
28
26
|
TRANSLATIONS = {
|
|
29
|
-
**PROSPECTIVE_TRANSLATIONS,
|
|
30
|
-
**TOPIC_ANALYSIS_TRANSLATIONS,
|
|
31
27
|
**DEMOS_UTILS_TRANSLATIONS,
|
|
28
|
+
**TOPIC_ANALYSIS_TRANSLATIONS,
|
|
32
29
|
**WEAK_SIGNALS_TRANSLATIONS,
|
|
33
30
|
}
|
|
34
31
|
|
|
@@ -39,12 +36,6 @@ LANGUAGES = {"fr": "Français", "en": "English"}
|
|
|
39
36
|
DEFAULT_LANGUAGE = "en"
|
|
40
37
|
|
|
41
38
|
|
|
42
|
-
def set_default_internationalization_language(language: str) -> None:
|
|
43
|
-
"""Set the default language for the application."""
|
|
44
|
-
global DEFAULT_LANGUAGE
|
|
45
|
-
DEFAULT_LANGUAGE = language
|
|
46
|
-
|
|
47
|
-
|
|
48
39
|
def get_current_internationalization_language() -> str:
|
|
49
40
|
"""Get the currently selected language from the session state."""
|
|
50
41
|
if "internationalization_language" not in st.session_state:
|
|
@@ -73,7 +64,7 @@ def create_internationalization_language_selector() -> None:
|
|
|
73
64
|
st.rerun()
|
|
74
65
|
|
|
75
66
|
|
|
76
|
-
def
|
|
67
|
+
def translate_helper(key: str, default: Optional[str] = None, translations=None) -> str:
|
|
77
68
|
"""
|
|
78
69
|
Translate a text key to the current language.
|
|
79
70
|
|
|
@@ -84,12 +75,28 @@ def translate(key: str, default: Optional[str] = None) -> str:
|
|
|
84
75
|
Returns:
|
|
85
76
|
The translated text in the current language
|
|
86
77
|
"""
|
|
78
|
+
if translations is None:
|
|
79
|
+
return key
|
|
87
80
|
lang = get_current_internationalization_language()
|
|
88
81
|
|
|
89
|
-
if key in
|
|
90
|
-
return
|
|
82
|
+
if key in translations and lang in translations[key]:
|
|
83
|
+
return translations[key][lang]
|
|
91
84
|
|
|
92
85
|
# If the key doesn't exist, or the language is not available for this key
|
|
93
86
|
if default:
|
|
94
87
|
return default
|
|
95
88
|
return key # Return the key itself as fallback
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def translate(key: str, default: Optional[str] = None) -> str:
|
|
92
|
+
"""
|
|
93
|
+
Translate a text key to the current language.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
key: The translation key to look up
|
|
97
|
+
default: Default text to return if the key is not found
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
The translated text in the current language
|
|
101
|
+
"""
|
|
102
|
+
return translate_helper(key, default, TRANSLATIONS)
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
#
|
|
7
7
|
|
|
8
8
|
# Starts the Summarizer app (a comparison of various method of text summarization)
|
|
9
|
-
|
|
9
|
+
streamlit run --theme.primaryColor royalblue summarization/summarizer_app.py
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2024, RTE (https://www.rte-france.com)
|
|
3
|
+
# See AUTHORS.txt
|
|
4
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
5
|
+
# This file is part of BERTrend.
|
|
6
|
+
#
|
|
7
|
+
# Use Python to load .env file and export variables
|
|
8
|
+
eval $(python3 << 'EOF'
|
|
9
|
+
from dotenv import dotenv_values
|
|
10
|
+
from dotenv import find_dotenv
|
|
11
|
+
|
|
12
|
+
# Find .env file starting from current directory
|
|
13
|
+
dotenv_path = find_dotenv(usecwd=True)
|
|
14
|
+
|
|
15
|
+
if dotenv_path:
|
|
16
|
+
# Load only the variables from .env file (not all environment)
|
|
17
|
+
env_vars = dotenv_values(dotenv_path)
|
|
18
|
+
|
|
19
|
+
# Export only the variables from .env
|
|
20
|
+
for key, value in env_vars.items():
|
|
21
|
+
if value is not None: # Skip empty values
|
|
22
|
+
# Escape special characters in the value
|
|
23
|
+
value_escaped = value.replace('"', '\\"')
|
|
24
|
+
print(f'export {key}="{value_escaped}"')
|
|
25
|
+
else:
|
|
26
|
+
import sys
|
|
27
|
+
print('echo "Warning: .env file not found"', file=sys.stderr)
|
|
28
|
+
EOF
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Set logs directory and create if not exists
|
|
32
|
+
export BERTREND_LOGS_DIR=$BERTREND_BASE_DIR/logs/bertrend
|
|
33
|
+
mkdir -p $BERTREND_LOGS_DIR
|
|
34
|
+
|
|
35
|
+
echo "Starting BERTrend Topic Analysis demo"
|
|
36
|
+
cd `pwd`/topic_analysis && CUDA_VISIBLE_DEVICES=0 streamlit run app.py 2>&1 | tee -a $BERTREND_LOGS_DIR/topic_analysis_demo.log
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2024, RTE (https://www.rte-france.com)
|
|
3
|
+
# See AUTHORS.txt
|
|
4
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
5
|
+
# This file is part of BERTrend.
|
|
6
|
+
#
|
|
7
|
+
# Use Python to load .env file and export variables
|
|
8
|
+
eval $(python3 << 'EOF'
|
|
9
|
+
from dotenv import dotenv_values
|
|
10
|
+
from dotenv import find_dotenv
|
|
11
|
+
|
|
12
|
+
# Find .env file starting from current directory
|
|
13
|
+
dotenv_path = find_dotenv(usecwd=True)
|
|
14
|
+
|
|
15
|
+
if dotenv_path:
|
|
16
|
+
# Load only the variables from .env file (not all environment)
|
|
17
|
+
env_vars = dotenv_values(dotenv_path)
|
|
18
|
+
|
|
19
|
+
# Export only the variables from .env
|
|
20
|
+
for key, value in env_vars.items():
|
|
21
|
+
if value is not None: # Skip empty values
|
|
22
|
+
# Escape special characters in the value
|
|
23
|
+
value_escaped = value.replace('"', '\\"')
|
|
24
|
+
print(f'export {key}="{value_escaped}"')
|
|
25
|
+
else:
|
|
26
|
+
import sys
|
|
27
|
+
print('echo "Warning: .env file not found"', file=sys.stderr)
|
|
28
|
+
EOF
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Set logs directory and create if not exists
|
|
32
|
+
export BERTREND_LOGS_DIR=$BERTREND_BASE_DIR/logs/bertrend
|
|
33
|
+
mkdir -p $BERTREND_LOGS_DIR
|
|
34
|
+
|
|
35
|
+
echo "Starting BERTrend Weak Signal Analysis demo"
|
|
36
|
+
cd `pwd`/weak_signals && CUDA_VISIBLE_DEVICES=0 streamlit run app.py 2>&1 | tee -a $BERTREND_LOGS_DIR/weak_signals_demo.log
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
*.egg-info/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
*.egg
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
ENV/
|
|
16
|
+
.venv
|
|
17
|
+
|
|
18
|
+
# IDE
|
|
19
|
+
.vscode/
|
|
20
|
+
.idea/
|
|
21
|
+
*.swp
|
|
22
|
+
*.swo
|
|
23
|
+
*~
|
|
24
|
+
|
|
25
|
+
# OS
|
|
26
|
+
.DS_Store
|
|
27
|
+
Thumbs.db
|
|
28
|
+
|
|
29
|
+
# Project specific
|
|
30
|
+
*.sqlite
|
|
31
|
+
*.db
|
|
32
|
+
data/
|
|
33
|
+
logs/
|
|
34
|
+
*.log
|
|
35
|
+
|
|
36
|
+
# Git
|
|
37
|
+
.git/
|
|
38
|
+
.gitignore
|
|
39
|
+
|
|
40
|
+
# Docker
|
|
41
|
+
Dockerfile
|
|
42
|
+
docker-compose.yml
|
|
43
|
+
.dockerignore
|
|
44
|
+
|
|
45
|
+
# Documentation
|
|
46
|
+
README.md
|
|
47
|
+
*.md
|
|
48
|
+
|
|
49
|
+
# Tests
|
|
50
|
+
tests/
|
|
51
|
+
test_*.py
|
|
52
|
+
*_test.py
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# Job Scheduler - Docker Setup
|
|
2
|
+
|
|
3
|
+
A FastAPI-based job scheduler with persistent SQLite storage and ProcessPoolExecutor, containerized with Docker.
|
|
4
|
+
|
|
5
|
+
## 📁 Project Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
job-scheduler/
|
|
9
|
+
├── main.py # FastAPI application
|
|
10
|
+
├── requirements.txt # Python dependencies
|
|
11
|
+
├── Dockerfile # Docker image definition
|
|
12
|
+
├── docker-compose.yml # Docker Compose configuration
|
|
13
|
+
├── .dockerignore # Docker ignore patterns
|
|
14
|
+
├── data/ # SQLite database (persistent)
|
|
15
|
+
│ └── jobs.sqlite
|
|
16
|
+
└── logs/ # Application logs (optional)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 🚀 Quick Start
|
|
20
|
+
|
|
21
|
+
### 1. Build and Run
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Build and start the container
|
|
25
|
+
docker-compose up -d
|
|
26
|
+
|
|
27
|
+
# View logs
|
|
28
|
+
docker-compose logs -f
|
|
29
|
+
|
|
30
|
+
# Check status
|
|
31
|
+
docker-compose ps
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Access the API
|
|
35
|
+
|
|
36
|
+
- **API Base URL**: http://localhost:8000
|
|
37
|
+
- **API Documentation**: http://localhost:8000/docs
|
|
38
|
+
- **Health Check**: http://localhost:8000/
|
|
39
|
+
|
|
40
|
+
### 3. Create Your First Job
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Create a job that runs every minute
|
|
44
|
+
curl -X POST "http://localhost:8000/jobs" \
|
|
45
|
+
-H "Content-Type: application/json" \
|
|
46
|
+
-d '{
|
|
47
|
+
"job_id": "test_job",
|
|
48
|
+
"job_type": "interval",
|
|
49
|
+
"function_name": "sample_job",
|
|
50
|
+
"minutes": 1,
|
|
51
|
+
"kwargs": {"message": "Hello from Docker!"}
|
|
52
|
+
}'
|
|
53
|
+
|
|
54
|
+
# List all jobs
|
|
55
|
+
curl http://localhost:8000/jobs
|
|
56
|
+
|
|
57
|
+
# Check job details
|
|
58
|
+
curl http://localhost:8000/jobs/test_job
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 🛠️ Docker Commands
|
|
62
|
+
|
|
63
|
+
### Basic Operations
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Start services
|
|
67
|
+
docker-compose up -d
|
|
68
|
+
|
|
69
|
+
# Stop services
|
|
70
|
+
docker-compose down
|
|
71
|
+
|
|
72
|
+
# Restart services
|
|
73
|
+
docker-compose restart
|
|
74
|
+
|
|
75
|
+
# View logs
|
|
76
|
+
docker-compose logs -f scheduler
|
|
77
|
+
|
|
78
|
+
# Execute commands in container
|
|
79
|
+
docker-compose exec scheduler bash
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Database Management
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Backup database
|
|
86
|
+
docker-compose exec scheduler cp /app/data/jobs.sqlite /app/data/jobs_backup.sqlite
|
|
87
|
+
|
|
88
|
+
# Access database
|
|
89
|
+
docker-compose exec scheduler sqlite3 /app/data/jobs.sqlite
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Rebuilding
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Rebuild after code changes
|
|
96
|
+
docker-compose up -d --build
|
|
97
|
+
|
|
98
|
+
# Force rebuild
|
|
99
|
+
docker-compose build --no-cache
|
|
100
|
+
docker-compose up -d
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## 📊 Monitoring
|
|
104
|
+
|
|
105
|
+
### Health Check
|
|
106
|
+
|
|
107
|
+
The container includes automatic health checks:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Check container health
|
|
111
|
+
docker-compose ps
|
|
112
|
+
|
|
113
|
+
# Manual health check
|
|
114
|
+
curl http://localhost:8000/
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Logs
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# View real-time logs
|
|
121
|
+
docker-compose logs -f
|
|
122
|
+
|
|
123
|
+
# View last 100 lines
|
|
124
|
+
docker-compose logs --tail=100
|
|
125
|
+
|
|
126
|
+
# View logs from specific service
|
|
127
|
+
docker-compose logs scheduler
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 🔧 Configuration
|
|
131
|
+
|
|
132
|
+
### Environment Variables
|
|
133
|
+
|
|
134
|
+
Edit `docker-compose.yml` to customize:
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
environment:
|
|
138
|
+
- TZ=Europe/Paris # Timezone
|
|
139
|
+
- LOG_LEVEL=INFO # Logging level
|
|
140
|
+
- MAX_WORKERS=5 # ProcessPoolExecutor workers
|
|
141
|
+
- DB_PATH=/app/data/jobs.sqlite
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Resource Limits
|
|
145
|
+
|
|
146
|
+
Adjust CPU and memory limits in `docker-compose.yml`:
|
|
147
|
+
|
|
148
|
+
```yaml
|
|
149
|
+
deploy:
|
|
150
|
+
resources:
|
|
151
|
+
limits:
|
|
152
|
+
cpus: '2'
|
|
153
|
+
memory: 1G
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Port Mapping
|
|
157
|
+
|
|
158
|
+
Change the exposed port:
|
|
159
|
+
|
|
160
|
+
```yaml
|
|
161
|
+
ports:
|
|
162
|
+
- "8080:8000" # Host:Container
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## 💾 Data Persistence
|
|
166
|
+
|
|
167
|
+
The SQLite database is stored in `./data/jobs.sqlite` on your host machine, ensuring jobs persist across container restarts.
|
|
168
|
+
|
|
169
|
+
### Backup Strategy
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Manual backup
|
|
173
|
+
cp data/jobs.sqlite data/jobs_backup_$(date +%Y%m%d).sqlite
|
|
174
|
+
|
|
175
|
+
# Automated backup script
|
|
176
|
+
#!/bin/bash
|
|
177
|
+
docker-compose exec scheduler sqlite3 /app/data/jobs.sqlite ".backup '/app/data/backup_$(date +%Y%m%d_%H%M%S).sqlite'"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## 🔍 Troubleshooting
|
|
181
|
+
|
|
182
|
+
### Container won't start
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# Check logs
|
|
186
|
+
docker-compose logs
|
|
187
|
+
|
|
188
|
+
# Rebuild
|
|
189
|
+
docker-compose down
|
|
190
|
+
docker-compose up -d --build
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Database locked
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Stop all instances
|
|
197
|
+
docker-compose down
|
|
198
|
+
|
|
199
|
+
# Remove stale locks
|
|
200
|
+
rm data/jobs.sqlite-journal
|
|
201
|
+
|
|
202
|
+
# Restart
|
|
203
|
+
docker-compose up -d
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Permission issues
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Fix permissions
|
|
210
|
+
sudo chown -R $USER:$USER data/
|
|
211
|
+
chmod -R 755 data/
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 🚢 Production Deployment
|
|
215
|
+
|
|
216
|
+
### Using Docker Swarm
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Initialize swarm
|
|
220
|
+
docker swarm init
|
|
221
|
+
|
|
222
|
+
# Deploy stack
|
|
223
|
+
docker stack deploy -c docker-compose.yml scheduler
|
|
224
|
+
|
|
225
|
+
# Check services
|
|
226
|
+
docker stack services scheduler
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Using Kubernetes
|
|
230
|
+
|
|
231
|
+
Create `deployment.yaml`:
|
|
232
|
+
|
|
233
|
+
```yaml
|
|
234
|
+
apiVersion: apps/v1
|
|
235
|
+
kind: Deployment
|
|
236
|
+
metadata:
|
|
237
|
+
name: job-scheduler
|
|
238
|
+
spec:
|
|
239
|
+
replicas: 1
|
|
240
|
+
selector:
|
|
241
|
+
matchLabels:
|
|
242
|
+
app: scheduler
|
|
243
|
+
template:
|
|
244
|
+
metadata:
|
|
245
|
+
labels:
|
|
246
|
+
app: scheduler
|
|
247
|
+
spec:
|
|
248
|
+
containers:
|
|
249
|
+
- name: scheduler
|
|
250
|
+
image: job-scheduler:latest
|
|
251
|
+
ports:
|
|
252
|
+
- containerPort: 8000
|
|
253
|
+
volumeMounts:
|
|
254
|
+
- name: data
|
|
255
|
+
mountPath: /app/data
|
|
256
|
+
volumes:
|
|
257
|
+
- name: data
|
|
258
|
+
persistentVolumeClaim:
|
|
259
|
+
claimName: scheduler-data
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## 📝 API Examples
|
|
263
|
+
|
|
264
|
+
### Cron Job (Daily at 9 AM Paris time)
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
curl -X POST "http://localhost:8000/jobs" \
|
|
268
|
+
-H "Content-Type: application/json" \
|
|
269
|
+
-d '{
|
|
270
|
+
"job_id": "daily_report",
|
|
271
|
+
"job_type": "cron",
|
|
272
|
+
"function_name": "report_generator",
|
|
273
|
+
"cron_expression": "0 9 * * *",
|
|
274
|
+
"kwargs": {"report_type": "daily"}
|
|
275
|
+
}'
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Validate Cron Expression
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
curl -X POST "http://localhost:8000/cron/validate" \
|
|
282
|
+
-H "Content-Type: application/json" \
|
|
283
|
+
-d '{"expression": "*/15 * * * *"}'
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Get Cron Examples
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
curl http://localhost:8000/cron/examples
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## 🔐 Security Considerations
|
|
293
|
+
|
|
294
|
+
For production:
|
|
295
|
+
|
|
296
|
+
1. **Add authentication**: Implement API key or OAuth
|
|
297
|
+
2. **Use HTTPS**: Add reverse proxy (nginx/traefik)
|
|
298
|
+
3. **Limit exposure**: Use internal networks
|
|
299
|
+
4. **Regular backups**: Automated database backups
|
|
300
|
+
5. **Update dependencies**: Keep packages current
|
|
301
|
+
|
|
302
|
+
## 📚 Additional Resources
|
|
303
|
+
|
|
304
|
+
- [FastAPI Documentation](https://fastapi.tiangolo.com/)
|
|
305
|
+
- [APScheduler Documentation](https://apscheduler.readthedocs.io/)
|
|
306
|
+
- [Docker Documentation](https://docs.docker.com/)
|
|
307
|
+
|
|
308
|
+
## 📄 License
|
|
309
|
+
|
|
310
|
+
This project is provided as-is for educational and commercial use.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
# Set working directory
|
|
4
|
+
WORKDIR /app
|
|
5
|
+
|
|
6
|
+
# Set environment variables
|
|
7
|
+
ENV PYTHONUNBUFFERED=1 \
|
|
8
|
+
PYTHONDONTWRITEBYTECODE=1 \
|
|
9
|
+
PIP_NO_CACHE_DIR=1 \
|
|
10
|
+
PIP_DISABLE_PIP_VERSION_CHECK=1
|
|
11
|
+
|
|
12
|
+
# Copy requirements file
|
|
13
|
+
COPY requirements.txt .
|
|
14
|
+
|
|
15
|
+
# Install Python dependencies
|
|
16
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
17
|
+
|
|
18
|
+
# Copy application code
|
|
19
|
+
COPY . /app/bertrend/services/scheduling
|
|
20
|
+
|
|
21
|
+
# Expose port
|
|
22
|
+
EXPOSE 8000
|
|
23
|
+
|
|
24
|
+
# Health check
|
|
25
|
+
HEALTHCHECK --interval=60s --timeout=10s --start-period=5s --retries=3 \
|
|
26
|
+
CMD python -c "import requests; requests.get('http://localhost:8000/')" || exit 1
|
|
27
|
+
|
|
28
|
+
# Run the application
|
|
29
|
+
CMD ["uvicorn", "bertrend.services.scheduling.scheduling_service:app", "--host", "0.0.0.0", "--port", "8000"]
|