bertrend 0.4.0__tar.gz → 0.4.1__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.
Files changed (317) hide show
  1. {bertrend-0.4.0 → bertrend-0.4.1}/PKG-INFO +4 -1
  2. bertrend-0.4.1/bertrend/bertrend_apps/exploration/geoviz/.streamlit/config.toml +6 -0
  3. bertrend-0.4.1/bertrend/bertrend_apps/exploration/geoviz/app.py +174 -0
  4. bertrend-0.4.1/bertrend/bertrend_apps/exploration/geoviz/backend.py +190 -0
  5. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/config/services_default_config.toml +5 -1
  6. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/docker-compose.yml +3 -5
  7. bertrend-0.4.1/bertrend/services/scheduling/start_docker_scheduling_service.sh +16 -0
  8. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/summarizer.py +1 -1
  9. bertrend-0.4.1/bertrend/services/summary_client.py +70 -0
  10. bertrend-0.4.1/bertrend/services/summary_server/config/default_config.toml +3 -0
  11. bertrend-0.4.1/bertrend/services/summary_server/config/settings.py +32 -0
  12. bertrend-0.4.1/bertrend/services/summary_server/main.py +12 -0
  13. bertrend-0.4.1/bertrend/services/summary_server/models.py +30 -0
  14. bertrend-0.4.1/bertrend/services/summary_server/routers/info.py +33 -0
  15. bertrend-0.4.1/bertrend/services/summary_server/routers/summarize.py +87 -0
  16. bertrend-0.4.1/bertrend/services/summary_server/start.py +18 -0
  17. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/summarizer/test_summarizer.py +2 -2
  18. bertrend-0.4.1/bertrend/tests/services/summary/__init__.py +4 -0
  19. bertrend-0.4.1/bertrend/tests/services/summary/test_summary_client.py +182 -0
  20. bertrend-0.4.1/bertrend/tests/services/summary/test_summary_config.py +44 -0
  21. bertrend-0.4.1/bertrend/tests/services/summary/test_summary_server.py +230 -0
  22. bertrend-0.4.1/bertrend/tests/utils/__init__.py +4 -0
  23. {bertrend-0.4.0 → bertrend-0.4.1}/pyproject.toml +5 -2
  24. bertrend-0.4.0/bertrend/bertrend_apps/exploration/dataviz/Main_page.py +0 -10
  25. bertrend-0.4.0/bertrend/bertrend_apps/exploration/dataviz/pages/1_Data_feeds.py +0 -105
  26. bertrend-0.4.0/bertrend/bertrend_apps/exploration/geolocalization/entity_utils.py +0 -118
  27. bertrend-0.4.0/bertrend/bertrend_apps/exploration/geolocalization/spacy/common_factory.py +0 -142
  28. bertrend-0.4.0/bertrend/bertrend_apps/exploration/geolocalization/spacy/dbpedia.py +0 -204
  29. bertrend-0.4.0/bertrend/bertrend_apps/exploration/geolocalization/spacy/nlp.config +0 -37
  30. bertrend-0.4.0/bertrend/bertrend_apps/exploration/geolocalization/spacy/utils.py +0 -42
  31. bertrend-0.4.0/bertrend/bertrend_apps/services/queue_monitor/__init__.py +0 -5
  32. {bertrend-0.4.0 → bertrend-0.4.1}/AUTHORS.txt +0 -0
  33. {bertrend-0.4.0 → bertrend-0.4.1}/LICENSE.md +0 -0
  34. {bertrend-0.4.0 → bertrend-0.4.1}/README.md +0 -0
  35. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/BERTopicModel.py +0 -0
  36. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/BERTrend.py +0 -0
  37. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/__init__.py +0 -0
  38. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/article_scoring/__init__.py +0 -0
  39. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/article_scoring/article_scoring.py +0 -0
  40. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/article_scoring/prompts.py +0 -0
  41. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/article_scoring/scoring_agent.py +0 -0
  42. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/__init__.py +0 -0
  43. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/common/__init__.py +0 -0
  44. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/common/apscheduler_utils.py +0 -0
  45. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/common/crontab_utils.py +0 -0
  46. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/common/date_utils.py +0 -0
  47. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/common/mail_utils.py +0 -0
  48. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/common/scheduler_utils.py +0 -0
  49. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/feeds/arxiv_feed.toml +0 -0
  50. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/feeds/decarbonation_feed.toml +0 -0
  51. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/feeds/llm_en_feed.toml +0 -0
  52. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/feeds/llm_feed.toml +0 -0
  53. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/feeds/nlp_feed.toml +0 -0
  54. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/feeds/rte_feed.toml +0 -0
  55. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/newsletters/arxiv_newsletter_from_last.toml +0 -0
  56. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/newsletters/decarbonation_newsletter_from_last.toml +0 -0
  57. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/newsletters/llm_en_newsletter_from_last.toml +0 -0
  58. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/newsletters/llm_newsletter_from_last.toml +0 -0
  59. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/newsletters/nlp_newsletter_from_last.toml +0 -0
  60. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/config/newsletters/rte_newsletter_from_last.toml +0 -0
  61. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/__init__.py +0 -0
  62. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/__main__.py +0 -0
  63. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/arxiv_provider.py +0 -0
  64. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/atom_feed_provider.py +0 -0
  65. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/bing_news_provider.py +0 -0
  66. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/data_provider.py +0 -0
  67. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/data_provider_utils.py +0 -0
  68. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/google_news_provider.py +0 -0
  69. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/newscatcher_provider.py +0 -0
  70. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/rss_feed_provider.py +0 -0
  71. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/data_provider/utils.py +0 -0
  72. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/__init__.py +0 -0
  73. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/.streamlit/config.toml +0 -0
  74. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/__init__.py +0 -0
  75. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/app.py +0 -0
  76. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/app_utils.py +0 -0
  77. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/config.toml +0 -0
  78. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/import_extraction_article.ipynb +0 -0
  79. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/prompts.py +0 -0
  80. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/start_newsletter_generator.sh +0 -0
  81. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/tabs/__init__.py +0 -0
  82. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/tabs/tab1.py +0 -0
  83. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/tabs/tab2.py +0 -0
  84. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/curebot/tabs/tab3.py +0 -0
  85. {bertrend-0.4.0/bertrend/bertrend_apps/exploration/dataviz → bertrend-0.4.1/bertrend/bertrend_apps/exploration/geoviz}/__init__.py +0 -0
  86. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/start_apps.sh +0 -0
  87. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/exploration/stop_apps.sh +0 -0
  88. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/install_feeds_and_newsletters.py +0 -0
  89. {bertrend-0.4.0/bertrend/bertrend_apps/exploration/geolocalization → bertrend-0.4.1/bertrend/bertrend_apps/newsletters}/__init__.py +0 -0
  90. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/newsletters/__main__.py +0 -0
  91. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/newsletters/newsletter_generation.py +0 -0
  92. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/newsletters/utils.py +0 -0
  93. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/.streamlit/config.toml +0 -0
  94. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/.streamlit/secrets.toml.example +0 -0
  95. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/__init__.py +0 -0
  96. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/app.py +0 -0
  97. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/authentication.py +0 -0
  98. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/automated_report_generation.py +0 -0
  99. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/dashboard_analysis.py +0 -0
  100. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/dashboard_common.py +0 -0
  101. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/dashboard_comparative.py +0 -0
  102. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/dashboard_signals.py +0 -0
  103. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/data_model.py +0 -0
  104. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/detailed_report_template.html +0 -0
  105. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/feeds_common.py +0 -0
  106. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/feeds_config.py +0 -0
  107. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/feeds_data.py +0 -0
  108. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/i18n.py +0 -0
  109. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/i18n_translations.py +0 -0
  110. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/llm_utils.py +0 -0
  111. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/models_info.py +0 -0
  112. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/perf_utils.py +0 -0
  113. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/process_new_data.py +0 -0
  114. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/report_generation.py +0 -0
  115. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/report_generation_utils.py +0 -0
  116. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/start_demo.sh +0 -0
  117. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/prospective_demo/utils.py +0 -0
  118. {bertrend-0.4.0/bertrend/bertrend_apps/exploration/geolocalization/spacy → bertrend-0.4.1/bertrend/bertrend_apps/services}/__init__.py +0 -0
  119. {bertrend-0.4.0/bertrend/bertrend_apps/exploration/dataviz/pages → bertrend-0.4.1/bertrend/bertrend_apps/services/bertrend}/__init__.py +0 -0
  120. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/bertrend_service.py +0 -0
  121. {bertrend-0.4.0/bertrend/bertrend_apps/services/bertrend → bertrend-0.4.1/bertrend/bertrend_apps/services/bertrend/config}/__init__.py +0 -0
  122. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/config/default_config.toml +0 -0
  123. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/config/settings.py +0 -0
  124. {bertrend-0.4.0/bertrend/bertrend_apps/newsletters → bertrend-0.4.1/bertrend/bertrend_apps/services/bertrend/models}/__init__.py +0 -0
  125. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/models/bertrend_app_models.py +0 -0
  126. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/models/data_provider_models.py +0 -0
  127. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/models/newsletters_models.py +0 -0
  128. {bertrend-0.4.0/bertrend/bertrend_apps/services → bertrend-0.4.1/bertrend/bertrend_apps/services/bertrend/routers}/__init__.py +0 -0
  129. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/routers/bertrend_app.py +0 -0
  130. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/routers/data_provider.py +0 -0
  131. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/routers/info.py +0 -0
  132. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/routers/newsletters.py +0 -0
  133. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/start.py +0 -0
  134. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/status.py +0 -0
  135. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/bertrend/stop.py +0 -0
  136. {bertrend-0.4.0/bertrend/bertrend_apps/services/bertrend/config → bertrend-0.4.1/bertrend/bertrend_apps/services/queue_management}/__init__.py +0 -0
  137. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/queue_management/bertrend_worker.py +0 -0
  138. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/queue_management/client.py +0 -0
  139. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/queue_management/docker-compose-rabbitmq.yml +0 -0
  140. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/queue_management/queue_manager.py +0 -0
  141. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/queue_management/rabbitmq_config.py +0 -0
  142. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/queue_management/start_rabbitmq.sh +0 -0
  143. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/queue_monitor/.streamlit/config.toml +0 -0
  144. {bertrend-0.4.0/bertrend/bertrend_apps/services/queue_management → bertrend-0.4.1/bertrend/bertrend_apps/services/queue_monitor}/__init__.py +0 -0
  145. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/queue_monitor/app.py +0 -0
  146. {bertrend-0.4.0/bertrend/bertrend_apps/services/bertrend/models → bertrend-0.4.1/bertrend/bertrend_apps/services/utils}/__init__.py +0 -0
  147. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/bertrend_apps/services/utils/logging_utils.py +0 -0
  148. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/config/bertopic_default_config.toml +0 -0
  149. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/config/bertrend_default_config.toml +0 -0
  150. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/config/parameters.py +0 -0
  151. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/__init__.py +0 -0
  152. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/demos_utils/__init__.py +0 -0
  153. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/demos_utils/data_loading_component.py +0 -0
  154. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/demos_utils/embed_documents_component.py +0 -0
  155. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/demos_utils/i18n.py +0 -0
  156. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/demos_utils/i18n_translations.py +0 -0
  157. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/demos_utils/icons.py +0 -0
  158. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/demos_utils/parameters_component.py +0 -0
  159. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/demos_utils/state_utils.py +0 -0
  160. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/start_summarizer_app.sh +0 -0
  161. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/start_topic_analysis_app.sh +0 -0
  162. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/start_weak_signals_app.sh +0 -0
  163. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/streamlit_components/__init__.py +0 -0
  164. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/streamlit_components/clickable_df_component.py +0 -0
  165. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/streamlit_components/input_with_pills_component.py +0 -0
  166. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/summarization/__init__.py +0 -0
  167. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/summarization/summarizer_app.py +0 -0
  168. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/.streamlit/config.toml +0 -0
  169. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/__init__.py +0 -0
  170. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/app.py +0 -0
  171. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/app_utils.py +0 -0
  172. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/demo_pages/__init__.py +0 -0
  173. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/demo_pages/explore_topics.py +0 -0
  174. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/demo_pages/newsletters_generation.py +0 -0
  175. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/demo_pages/temporal_visualizations.py +0 -0
  176. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/demo_pages/topic_visualizations.py +0 -0
  177. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/demo_pages/training_page.py +0 -0
  178. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/topic_analysis/i18n_translations.py +0 -0
  179. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/weak_signals/.streamlit/config.toml +0 -0
  180. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/weak_signals/__init__.py +0 -0
  181. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/weak_signals/app.py +0 -0
  182. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/weak_signals/i18n_translations.py +0 -0
  183. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/demos/weak_signals/visualizations_utils.py +0 -0
  184. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/__init__.py +0 -0
  185. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/agent_utils.py +0 -0
  186. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/newsletter.css +0 -0
  187. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/newsletter_features.py +0 -0
  188. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/newsletter_model.py +0 -0
  189. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/newsletter_outlook_template.html +0 -0
  190. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/newsletter_template.html +0 -0
  191. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/openai_client.py +0 -0
  192. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/llm_utils/prompts.py +0 -0
  193. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/metrics/__init__.py +0 -0
  194. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/metrics/temporal_metrics_embedding.py +0 -0
  195. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/metrics/topic_metrics.py +0 -0
  196. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/resources/common_ngrams.json +0 -0
  197. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/resources/stopwords-en.json +0 -0
  198. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/resources/stopwords-fr.json +0 -0
  199. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/resources/stopwords-rte.json +0 -0
  200. {bertrend-0.4.0/bertrend/bertrend_apps/services/bertrend/routers → bertrend-0.4.1/bertrend/services}/__init__.py +0 -0
  201. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/authentication.py +0 -0
  202. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/cert.pem +0 -0
  203. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_client.py +0 -0
  204. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/README.md +0 -0
  205. {bertrend-0.4.0/bertrend/bertrend_apps/services/utils → bertrend-0.4.1/bertrend/services/embedding_server}/__init__.py +0 -0
  206. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/bertrend_client_registry.json +0 -0
  207. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/config/default_config.toml +0 -0
  208. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/config/settings.py +0 -0
  209. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/main.py +0 -0
  210. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/models.py +0 -0
  211. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/requirements.txt +0 -0
  212. {bertrend-0.4.0/bertrend/services → bertrend-0.4.1/bertrend/services/embedding_server/routers}/__init__.py +0 -0
  213. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/routers/authentication.py +0 -0
  214. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/routers/embeddings.py +0 -0
  215. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/routers/info.py +0 -0
  216. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/security.py +0 -0
  217. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/start.py +0 -0
  218. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/status.py +0 -0
  219. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_server/stop.py +0 -0
  220. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/embedding_service.py +0 -0
  221. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/key.pem +0 -0
  222. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/.dockerignore +0 -0
  223. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/Docker_setup.md +0 -0
  224. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/Dockerfile +0 -0
  225. {bertrend-0.4.0/bertrend/services/embedding_server → bertrend-0.4.1/bertrend/services/scheduling}/__init__.py +0 -0
  226. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/dashboard.html +0 -0
  227. {bertrend-0.4.0/bertrend/services/embedding_server/routers → bertrend-0.4.1/bertrend/services/scheduling/job_utils}/__init__.py +0 -0
  228. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/job_utils/job_functions.py +0 -0
  229. {bertrend-0.4.0/bertrend/services/scheduling → bertrend-0.4.1/bertrend/services/scheduling/models}/__init__.py +0 -0
  230. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/models/scheduling_models.py +0 -0
  231. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/requirements.txt +0 -0
  232. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/routers/info.py +0 -0
  233. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/routers/scheduling.py +0 -0
  234. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/scheduling/scheduling_service.py +0 -0
  235. {bertrend-0.4.0/bertrend/services/scheduling/job_utils → bertrend-0.4.1/bertrend/services/summary}/__init__.py +0 -0
  236. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/summary/abstractive_summarizer.py +0 -0
  237. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/summary/chatgpt_summarizer.py +0 -0
  238. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/summary/extractive_summarizer.py +0 -0
  239. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/summary/lexrank.py +0 -0
  240. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/services/summary/prompts.py +0 -0
  241. {bertrend-0.4.0/bertrend/services/scheduling/models → bertrend-0.4.1/bertrend/services/summary_server}/__init__.py +0 -0
  242. {bertrend-0.4.0/bertrend/services/summary → bertrend-0.4.1/bertrend/services/summary_server/config}/__init__.py +0 -0
  243. {bertrend-0.4.0/bertrend/tests → bertrend-0.4.1/bertrend/services/summary_server/routers}/__init__.py +0 -0
  244. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/README_integration_tests.md +0 -0
  245. {bertrend-0.4.0/bertrend/tests/apps → bertrend-0.4.1/bertrend/tests}/__init__.py +0 -0
  246. {bertrend-0.4.0/bertrend/tests/core → bertrend-0.4.1/bertrend/tests/apps}/__init__.py +0 -0
  247. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/apps/test_bertrend_service.py +0 -0
  248. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/apps/test_lazy_scheduler.py +0 -0
  249. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/apps/test_models.py +0 -0
  250. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/apps/test_multiworker.py +0 -0
  251. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/apps/test_process_new_data.py +0 -0
  252. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/apps/test_routers_bertrend_app.py +0 -0
  253. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/apps/test_routers_info.py +0 -0
  254. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/conftest.py +0 -0
  255. {bertrend-0.4.0/bertrend/tests/llm → bertrend-0.4.1/bertrend/tests/core}/__init__.py +0 -0
  256. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_bertrend.py +0 -0
  257. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_data_structure.py +0 -0
  258. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_representative_docs.py +0 -0
  259. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_temporal_metrics_embedding.py +0 -0
  260. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_topic_description.py +0 -0
  261. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_topic_metrics.py +0 -0
  262. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_topic_model.py +0 -0
  263. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_trend_analysis_data_structure.py +0 -0
  264. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_trend_analysis_prompts.py +0 -0
  265. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_trend_analysis_visualizations.py +0 -0
  266. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_trend_analysis_weak_signals.py +0 -0
  267. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/core/test_visualizations.py +0 -0
  268. {bertrend-0.4.0/bertrend/tests/services → bertrend-0.4.1/bertrend/tests/llm}/__init__.py +0 -0
  269. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/llm/test_agent_utils.py +0 -0
  270. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/llm/test_article_scoring.py +0 -0
  271. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/llm/test_article_scoring_models.py +0 -0
  272. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/llm/test_newsletter_features.py +0 -0
  273. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/llm/test_newsletter_model.py +0 -0
  274. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/llm/test_openai_client.py +0 -0
  275. {bertrend-0.4.0/bertrend/tests/services/embedding → bertrend-0.4.1/bertrend/tests/services}/__init__.py +0 -0
  276. {bertrend-0.4.0/bertrend/tests/services/queue → bertrend-0.4.1/bertrend/tests/services/embedding}/__init__.py +0 -0
  277. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/embedding/test_embedding_client.py +0 -0
  278. {bertrend-0.4.0/bertrend/tests/services/scheduling → bertrend-0.4.1/bertrend/tests/services/queue}/__init__.py +0 -0
  279. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/queue/test_bertrend_worker.py +0 -0
  280. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/queue/test_client.py +0 -0
  281. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/queue/test_queue_manager.py +0 -0
  282. {bertrend-0.4.0/bertrend/tests/services/summarizer → bertrend-0.4.1/bertrend/tests/services/scheduling}/__init__.py +0 -0
  283. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/scheduling/test_job_exception_fix.py +0 -0
  284. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/scheduling/test_scheduling_service.py +0 -0
  285. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/scheduling/test_stress_test.py +0 -0
  286. {bertrend-0.4.0/bertrend/tests/utils → bertrend-0.4.1/bertrend/tests/services/summarizer}/__init__.py +0 -0
  287. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/summarizer/test_abstractive_summarizer.py +0 -0
  288. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/summarizer/test_chatgpt_summarizer.py +0 -0
  289. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/services/summarizer/test_extractive_summarizer.py +0 -0
  290. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/test_installation.py +0 -0
  291. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/test_integration.py +0 -0
  292. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_apscheduler_utils.py +0 -0
  293. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_cache_utils.py +0 -0
  294. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_config_utils.py +0 -0
  295. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_crontab_utils.py +0 -0
  296. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_data_loading.py +0 -0
  297. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_date_utils.py +0 -0
  298. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_mail_utils.py +0 -0
  299. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_scheduler_utils.py +0 -0
  300. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/tests/utils/test_utils_init.py +0 -0
  301. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/topic_analysis/__init__.py +0 -0
  302. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/topic_analysis/data_structure.py +0 -0
  303. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/topic_analysis/prompts.py +0 -0
  304. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/topic_analysis/representative_docs.py +0 -0
  305. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/topic_analysis/topic_description.py +0 -0
  306. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/topic_analysis/visualizations.py +0 -0
  307. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/trend_analysis/__init__.py +0 -0
  308. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/trend_analysis/data_structure.py +0 -0
  309. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/trend_analysis/prompts.py +0 -0
  310. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/trend_analysis/signal_llm_template_en.html +0 -0
  311. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/trend_analysis/signal_llm_template_fr.html +0 -0
  312. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/trend_analysis/visualizations.py +0 -0
  313. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/trend_analysis/weak_signals.py +0 -0
  314. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/utils/__init__.py +0 -0
  315. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/utils/cache_utils.py +0 -0
  316. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/utils/config_utils.py +0 -0
  317. {bertrend-0.4.0 → bertrend-0.4.1}/bertrend/utils/data_loading.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bertrend
3
- Version: 0.4.0
3
+ Version: 0.4.1
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
@@ -28,7 +28,9 @@ Requires-Dist: dateparser (>=1.2.0)
28
28
  Requires-Dist: dill (>=0.4.0)
29
29
  Requires-Dist: fastapi (>=0.120.0)
30
30
  Requires-Dist: feedparser (>=6.0.11)
31
+ Requires-Dist: folium (>=0.20.0)
31
32
  Requires-Dist: gensim (>=4.3.3)
33
+ Requires-Dist: geopy (>=2.4.1)
32
34
  Requires-Dist: google-api-python-client (>=2.148.0)
33
35
  Requires-Dist: google-auth-oauthlib (>=1.2.1)
34
36
  Requires-Dist: googlenewsdecoder (>=0.1.7)
@@ -69,6 +71,7 @@ Requires-Dist: sentencepiece (>=0.2.0)
69
71
  Requires-Dist: starlette (>=0.46.2)
70
72
  Requires-Dist: streamlit (>=1.51.0)
71
73
  Requires-Dist: streamlit-code-editor (>=0.1.22)
74
+ Requires-Dist: streamlit-folium (>=0.26.1)
72
75
  Requires-Dist: supervisor (>=4.3.0)
73
76
  Requires-Dist: thefuzz (>=0.22.1)
74
77
  Requires-Dist: tiktoken (>=0.8.0)
@@ -0,0 +1,6 @@
1
+ [theme]
2
+ primaryColor = "royalblue"
3
+ baseFontSize = 13
4
+
5
+ [server]
6
+ port = 8089
@@ -0,0 +1,174 @@
1
+ # Copyright (c) 2024-2026, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # SPDX-License-Identifier: MPL-2.0
4
+ # This file is part of BERTrend.
5
+
6
+ import backend # Importing our isolated logic
7
+ import folium
8
+ import pandas as pd
9
+ import streamlit as st
10
+ from dotenv import load_dotenv
11
+ from folium.plugins import MarkerCluster
12
+ from streamlit_folium import st_folium
13
+
14
+ # Load environment variables at module import
15
+ load_dotenv(override=True)
16
+
17
+ # --- Page Config ---
18
+ st.set_page_config(page_title="GeoNews Agent", layout="wide", page_icon="🌍")
19
+
20
+ st.title("🌍 GeoNews Mapper")
21
+ st.markdown("""
22
+ Extract geographical insights from news articles using AI.
23
+ This tool detects cities, departments, and regions and maps them.
24
+ """)
25
+
26
+ # --- Sidebar: Configuration ---
27
+ with st.sidebar:
28
+ st.header("Settings")
29
+
30
+ st.markdown("---")
31
+ st.markdown("**Hierarchy Logic:**")
32
+ st.caption("1. **Ville** (City)")
33
+ st.caption("2. **Département**")
34
+ st.caption("3. **Région**")
35
+
36
+ # --- Main Input Section ---
37
+ tab1, tab2 = st.tabs(["🔗 Paste URLs", "📂 Upload Data"])
38
+
39
+ input_data = []
40
+ input_type = ""
41
+
42
+ examples = [
43
+ "https://www.francebleu.fr/provence-alpes-cote-d-azur/bouches-du-rhone-13/ligne-tht-en-camargue-malgre-les-risques-pour-les-especes-protegees-rte-maintient-son-projet-5901415",
44
+ "https://maritima.fr/actualites/economie/fos-sur-mer/10613/ligne-tres-haute-tension-vers-fos-letat-veut-que-rte-poursuive-les-travaux",
45
+ ]
46
+
47
+ with tab1:
48
+ urls_input = st.text_area(
49
+ "Enter News URLs (one per line)",
50
+ value="\n".join(examples),
51
+ height=150,
52
+ placeholder="https://www.lemonde.fr/...\nhttps://www.lefigaro.fr/...",
53
+ )
54
+ if urls_input:
55
+ input_data = [url.strip() for url in urls_input.split("\n") if url.strip()]
56
+ input_type = "url"
57
+
58
+ with tab2:
59
+ uploaded_file = st.file_uploader(
60
+ "Upload CSV or Excel (Column must be named 'text' or 'url')",
61
+ type=["csv", "xlsx"],
62
+ )
63
+ if uploaded_file:
64
+ if uploaded_file.name.endswith(".csv"):
65
+ df_upload = pd.read_csv(uploaded_file)
66
+ else:
67
+ df_upload = pd.read_excel(uploaded_file)
68
+
69
+ # Detect column
70
+ if "url" in df_upload.columns:
71
+ input_data = df_upload["url"].tolist()
72
+ input_type = "url"
73
+ elif "text" in df_upload.columns:
74
+ input_data = df_upload["text"].tolist()
75
+ input_type = "text"
76
+ else:
77
+ st.error("File must contain a 'url' or 'text' column.")
78
+
79
+ # --- Execution ---
80
+ if st.button("🚀 Extract & Map Locations"):
81
+ if not input_data:
82
+ st.warning("Please provide input URLs or text.")
83
+ else:
84
+ with st.spinner("🕵️‍♂️ Agent is reading articles and extracting locations..."):
85
+ # Call the backend
86
+ result_df = backend.extract_geo_data(input_data, input_type)
87
+
88
+ if result_df.empty:
89
+ st.error("No locations found or extraction failed.")
90
+ else:
91
+ st.session_state["geo_data"] = result_df
92
+ st.success(f"Extracted {len(result_df)} locations!")
93
+
94
+ # --- Visualization Section ---
95
+ if "geo_data" in st.session_state:
96
+ df = st.session_state["geo_data"]
97
+
98
+ st.divider()
99
+
100
+ # 1. Search / Filters
101
+ col_filter1, col_filter2 = st.columns(2)
102
+ with col_filter1:
103
+ # Get unique regions, filter out Nones
104
+ regions = ["All"] + sorted([x for x in df["region"].unique() if x])
105
+ selected_region = st.selectbox("Filter by Region", regions)
106
+
107
+ with col_filter2:
108
+ search_query = st.text_input("Search for a specific City or Department")
109
+
110
+ # Apply filters
111
+ filtered_df = df.copy()
112
+ if selected_region != "All":
113
+ filtered_df = filtered_df[filtered_df["region"] == selected_region]
114
+
115
+ if search_query:
116
+ filtered_df = filtered_df[
117
+ filtered_df["city"].str.contains(search_query, case=False, na=False)
118
+ | filtered_df["department"].str.contains(search_query, case=False, na=False)
119
+ ]
120
+
121
+ # 2. Map Layout
122
+ col_map, col_data = st.columns([2, 1])
123
+
124
+ with col_map:
125
+ st.subheader("Interactive Map")
126
+
127
+ # Initialize Map centered on France
128
+ m = folium.Map(location=[46.603354, 1.888334], zoom_start=6)
129
+
130
+ # Marker Cluster Group (Prevents overwhelm)
131
+ marker_cluster = MarkerCluster().add_to(m)
132
+
133
+ for idx, row in filtered_df.iterrows():
134
+ # Determine what to show as the title
135
+ if row["specific_location"]:
136
+ display_title = row["specific_location"]
137
+ display_subtitle = f"{row['city']}, {row['country']}"
138
+ else:
139
+ display_title = row["city"]
140
+ display_subtitle = f"{row['department'] or ''} - {row['country']}"
141
+
142
+ html = f"""
143
+ <b>{display_title}</b><br>
144
+ <span style='color:grey; font-size:10px'>{display_subtitle}</span><br>
145
+ <hr style='margin:5px 0'>
146
+ <i>"{row["snippet"]}"</i><br>
147
+ <a href='{row["source"]}' target='_blank'>Source</a>
148
+ """
149
+
150
+ folium.Marker(
151
+ location=[row["lat"], row["lon"]],
152
+ tooltip=row["city"],
153
+ popup=folium.Popup(html, max_width=300),
154
+ icon=folium.Icon(color="blue", icon="info-sign"),
155
+ ).add_to(marker_cluster)
156
+
157
+ st_folium(m, width="100%", height=600)
158
+
159
+ with col_data:
160
+ st.subheader("Extracted Data")
161
+ st.dataframe(
162
+ filtered_df[["city", "department", "region", "snippet"]],
163
+ hide_index=True,
164
+ height=600,
165
+ )
166
+
167
+ # Export
168
+ csv = filtered_df.to_csv(index=False).encode("utf-8")
169
+ st.download_button(
170
+ "📥 Download Data as CSV",
171
+ data=csv,
172
+ file_name="geo_news_data.csv",
173
+ mime="text/csv",
174
+ )
@@ -0,0 +1,190 @@
1
+ from typing import List, Optional
2
+
3
+ import pandas as pd
4
+ from geopy.extra.rate_limiter import RateLimiter
5
+ from geopy.geocoders import Nominatim
6
+ from goose3 import Goose
7
+ from pydantic import BaseModel, Field
8
+
9
+ from bertrend.llm_utils.openai_client import OpenAI_Client
10
+
11
+
12
+ # --- Data Models ---
13
+ class GeoLocation(BaseModel):
14
+ specific_location: Optional[str] = Field(
15
+ None,
16
+ description="A specific landmark, building, district, or street (e.g., 'Tour Eiffel', 'Gare de Lyon', 'Brooklyn Bridge').",
17
+ )
18
+ city: str = Field(..., description="The city or municipality.")
19
+ department: Optional[str] = Field(
20
+ None,
21
+ description="The administrative department, state, or province (e.g., 'Gironde', 'California').",
22
+ )
23
+ region: Optional[str] = Field(
24
+ None,
25
+ description="The larger administrative region (e.g., 'Nouvelle-Aquitaine').",
26
+ )
27
+ country: str = Field(
28
+ ...,
29
+ description="The country where this location is found (e.g., 'France', 'USA').",
30
+ )
31
+ context_snippet: str = Field(
32
+ ...,
33
+ description="A short snippet of text justifying why this location was extracted.",
34
+ )
35
+
36
+
37
+ class ArticleLocations(BaseModel):
38
+ locations: List[GeoLocation]
39
+
40
+
41
+ # --- Helper Functions ---
42
+
43
+
44
+ def fetch_text_from_url(url: str) -> str:
45
+ """
46
+ Uses Goose3 to extract the main content of the article,
47
+ stripping out ads, menus, and html clutter.
48
+ """
49
+ try:
50
+ g = Goose()
51
+ article = g.extract(url=url)
52
+ text = article.cleaned_text
53
+ g.close()
54
+
55
+ if not text:
56
+ return ""
57
+
58
+ # Truncate if extremely long to save OpenAI tokens
59
+ return text[:15000]
60
+
61
+ except Exception as e:
62
+ print(f"Goose extraction error for {url}: {e}")
63
+ return ""
64
+
65
+
66
+ def geocode_locations(df: pd.DataFrame) -> pd.DataFrame:
67
+ """
68
+ Adds Lat/Lon using a hierarchical strategy to ensure the most precise
69
+ location is found while maintaining a fallback for broader searches.
70
+ """
71
+ # Unique user_agent prevents 403 errors
72
+ geolocator = Nominatim(user_agent="geo_news_agent_app_v5")
73
+ geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
74
+
75
+ lats = []
76
+ lons = []
77
+
78
+ print("Geocoding locations...")
79
+
80
+ for _, row in df.iterrows():
81
+ location = None
82
+
83
+ # 1. Strategy: Specific Landmark Precision
84
+ # Query: "Tour Eiffel, Paris, France"
85
+ if row.get("specific_location"):
86
+ query = f"{row['specific_location']}, {row['city']}, {row['country']}"
87
+ try:
88
+ location = geocode(query)
89
+ except:
90
+ pass
91
+
92
+ # 2. Strategy: Administrative Precision
93
+ # Query: "Paris, Ile-de-France, France"
94
+ if not location and row.get("department"):
95
+ query = f"{row['city']}, {row['department']}, {row['country']}"
96
+ try:
97
+ location = geocode(query)
98
+ except:
99
+ pass
100
+
101
+ # 3. Strategy: City Fallback
102
+ # Query: "Paris, France"
103
+ if not location:
104
+ query = f"{row['city']}, {row['country']}"
105
+ try:
106
+ location = geocode(query)
107
+ except:
108
+ pass
109
+
110
+ if location:
111
+ lats.append(location.latitude)
112
+ lons.append(location.longitude)
113
+ else:
114
+ lats.append(None)
115
+ lons.append(None)
116
+
117
+ df["lat"] = lats
118
+ df["lon"] = lons
119
+
120
+ # Return only rows where we successfully found coordinates
121
+ return df.dropna(subset=["lat", "lon"])
122
+
123
+
124
+ # --- Main Agent Function ---
125
+
126
+
127
+ def extract_geo_data(inputs: List[str], input_type: str) -> pd.DataFrame:
128
+ """
129
+ Main pipeline:
130
+ 1. Gets text (using Goose3 if URL).
131
+ 2. Calls OpenAI to extract structured hierarchy including specific landmarks and country.
132
+ 3. Aggregates results and geocodes them.
133
+ """
134
+ client = OpenAI_Client()
135
+ all_results = []
136
+
137
+ for item in inputs:
138
+ # 1. Prepare Text
139
+ if input_type == "url":
140
+ text_content = fetch_text_from_url(item)
141
+ source_id = item
142
+ else:
143
+ text_content = item
144
+ source_id = "Uploaded Text"
145
+
146
+ # Skip empty extractions
147
+ if not text_content or len(text_content) < 50:
148
+ continue
149
+
150
+ # 2. Call OpenAI Agent
151
+ try:
152
+ system_prompt = (
153
+ "You are a geographical extraction specialist. Extract all relevant physical locations mentioned in the text. "
154
+ "For each location, provide the following hierarchy:\n"
155
+ "1. **Specific Location**: A landmark, building, square, or district (e.g., 'Louvre Museum', 'La Défense'). If none, leave null.\n"
156
+ "2. **City**: The municipality.\n"
157
+ "3. **Department**: The state, province, or department.\n"
158
+ "4. **Country**: Crucial. Infer it if not explicit (e.g., London -> UK).\n"
159
+ "Provide a context snippet explaining the relevance."
160
+ )
161
+
162
+ extracted = client.parse(
163
+ system_prompt=system_prompt,
164
+ user_prompt=text_content,
165
+ response_format=ArticleLocations,
166
+ )
167
+
168
+ # 3. Flatten results
169
+ for loc in extracted.locations:
170
+ all_results.append(
171
+ {
172
+ "source": source_id,
173
+ "specific_location": loc.specific_location,
174
+ "city": loc.city,
175
+ "department": loc.department,
176
+ "region": loc.region,
177
+ "country": loc.country,
178
+ "snippet": loc.context_snippet,
179
+ }
180
+ )
181
+
182
+ except Exception as e:
183
+ print(f"Error processing {source_id}: {e}")
184
+
185
+ df = pd.DataFrame(all_results)
186
+
187
+ if not df.empty:
188
+ df = geocode_locations(df)
189
+
190
+ return df
@@ -29,4 +29,8 @@ base_url = "$OPENAI_BASE_URL"
29
29
  model = "$OPENAI_DEFAULT_MODEL"
30
30
  temperature = 0.1
31
31
  max_output_tokens = 2048
32
- system_prompt = "You are a helpful assistant, skilled in detailing topic evolution over time for the detection of emerging trends and signals."
32
+ system_prompt = "You are a helpful assistant, skilled in detailing topic evolution over time for the detection of emerging trends and signals."
33
+
34
+ # Summary service parameters
35
+ [summary_service]
36
+ url = "$SUMMARY_SERVICE_URL"
@@ -9,18 +9,17 @@ services:
9
9
  - "8882:8000"
10
10
  volumes:
11
11
  # Mount data directory for persistent SQLite database
12
- - $HOME/.bertrend/db:$HOME/.bertrend/db
12
+ # Host path uses $HOME, container path uses /home/user
13
+ - ${HOME}/.bertrend/db:/home/user/.bertrend/db
13
14
  environment:
14
15
  - NO_PROXY=$NO_PROXY # to avoid communication issues
15
16
  - no_proxy=$no_proxy # to avoid communication issues
16
17
  # Application settings
17
18
  - TZ=Europe/Paris
18
19
  - PYTHONUNBUFFERED=1
19
- # Optional: Log level
20
20
  - LOG_LEVEL=DEBUG
21
- # Optional: Number of worker processes
22
21
  - MAX_WORKERS=100
23
- - HOME=$HOME
22
+ - HOME=/home/user # Generic home path in container
24
23
  restart: always
25
24
  logging:
26
25
  driver: "json-file"
@@ -35,7 +34,6 @@ services:
35
34
  start_period: 10s
36
35
  networks:
37
36
  - scheduler-network
38
- # Resource limits (adjust based on your needs)
39
37
  deploy:
40
38
  resources:
41
39
  limits:
@@ -0,0 +1,16 @@
1
+ #
2
+ # Copyright (c) 2024-2026, 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
+
8
+ # Create directory on host
9
+ mkdir -p ~/.bertrend/db
10
+
11
+ # Export your UID/GID (add to your shell profile for persistence)
12
+ export UID=$(id -u)
13
+ export GID=$(id -g)
14
+
15
+ # Run docker compose
16
+ docker compose up --build --force-recreate -d
@@ -34,7 +34,7 @@ class Summarizer(ABC):
34
34
  """Basic implementation of batch summarization. Can be overridden by subclasses."""
35
35
  return [
36
36
  self.generate_summary(
37
- article_text=t,
37
+ t,
38
38
  max_sentences=max_sentences,
39
39
  max_words=max_words,
40
40
  max_length_ratio=max_length_ratio,
@@ -0,0 +1,70 @@
1
+ # Copyright (c) 2024-2026, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # SPDX-License-Identifier: MPL-2.0
4
+ # This file is part of BERTrend.
5
+
6
+ import requests
7
+
8
+
9
+ class SummaryAPIClient:
10
+ """Thin HTTP client for the BERTrend Summarization Service."""
11
+
12
+ def __init__(self, url: str = "http://localhost:6465"):
13
+ self.url = url.rstrip("/")
14
+
15
+ def health(self) -> dict:
16
+ """Check service health."""
17
+ resp = requests.get(f"{self.url}/health")
18
+ resp.raise_for_status()
19
+ return resp.json()
20
+
21
+ def list_summarizers(self) -> list[dict]:
22
+ """List available summarizers and their status."""
23
+ resp = requests.get(f"{self.url}/summarizers")
24
+ resp.raise_for_status()
25
+ return resp.json()
26
+
27
+ def summarize(
28
+ self,
29
+ text: str | list[str],
30
+ summarizer_type: str = "llm",
31
+ language: str = "fr",
32
+ max_sentences: int = 3,
33
+ max_words: int | None = None,
34
+ max_length_ratio: float = 0.2,
35
+ ) -> dict:
36
+ """Summarize one or more texts.
37
+
38
+ Parameters
39
+ ----------
40
+ text : str | list[str]
41
+ Text(s) to summarize.
42
+ summarizer_type : str
43
+ Summarizer backend: "llm", "extractive", or "enhanced".
44
+ language : str
45
+ Prompt language ("fr" or "en").
46
+ max_sentences : int
47
+ Maximum number of sentences in the summary.
48
+ max_words : int | None
49
+ Maximum number of words (optional).
50
+ max_length_ratio : float
51
+ Maximum ratio of summary length to original.
52
+
53
+ Returns
54
+ -------
55
+ dict
56
+ Response with keys: summaries, summarizer_type, language, processing_time_ms.
57
+ """
58
+ payload = {
59
+ "text": text,
60
+ "summarizer_type": summarizer_type,
61
+ "language": language,
62
+ "max_sentences": max_sentences,
63
+ "max_length_ratio": max_length_ratio,
64
+ }
65
+ if max_words is not None:
66
+ payload["max_words"] = max_words
67
+
68
+ resp = requests.post(f"{self.url}/summarize", json=payload)
69
+ resp.raise_for_status()
70
+ return resp.json()
@@ -0,0 +1,3 @@
1
+ host = "0.0.0.0"
2
+ port = 8885
3
+ number_workers = 1
@@ -0,0 +1,32 @@
1
+ # Copyright (c) 2024-2026, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # SPDX-License-Identifier: MPL-2.0
4
+ # This file is part of BERTrend.
5
+
6
+ import os
7
+ import tomllib
8
+ from pathlib import Path
9
+
10
+ from pydantic_settings import BaseSettings
11
+
12
+ DEFAULT_CONFIG_FILE = Path(__file__).parent / "default_config.toml"
13
+
14
+
15
+ class SummaryAPIConfig(BaseSettings):
16
+ host: str
17
+ port: int
18
+ number_workers: int
19
+
20
+
21
+ def get_config() -> SummaryAPIConfig:
22
+ """
23
+ Return the configuration for the summary API.
24
+ The configuration is loaded from a toml file.
25
+ The path to the toml file can be specified using the environment variable `SUMMARY_API_CONFIG_FILE`.
26
+ If the environment variable is not set, the default configuration file is used.
27
+ """
28
+ config_file = os.environ.get("SUMMARY_API_CONFIG_FILE", None)
29
+ if config_file is None:
30
+ config_file = DEFAULT_CONFIG_FILE
31
+ with open(config_file, "rb") as f:
32
+ return SummaryAPIConfig(**tomllib.load(f))
@@ -0,0 +1,12 @@
1
+ # Copyright (c) 2024-2026, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # SPDX-License-Identifier: MPL-2.0
4
+ # This file is part of BERTrend.
5
+
6
+ from fastapi import FastAPI
7
+
8
+ from bertrend.services.summary_server.routers import info, summarize
9
+
10
+ app = FastAPI(title="BERTrend Summarization Service")
11
+ app.include_router(info.router, tags=["Info"])
12
+ app.include_router(summarize.router, tags=["Summarization"])
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 2024-2026, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # SPDX-License-Identifier: MPL-2.0
4
+ # This file is part of BERTrend.
5
+
6
+ from pydantic import BaseModel
7
+
8
+
9
+ class SummarizeRequest(BaseModel):
10
+ text: str | list[str]
11
+ summarizer_type: str = "llm"
12
+ language: str = "fr"
13
+ max_sentences: int = 3
14
+ max_words: int | None = None
15
+ max_length_ratio: float = 0.2
16
+
17
+
18
+ class SummarizeResponse(BaseModel):
19
+ summaries: list[str]
20
+ summarizer_type: str
21
+ language: str
22
+ processing_time_ms: float
23
+
24
+
25
+ class SummarizerInfo(BaseModel):
26
+ name: str
27
+ description: str
28
+ requires_api_key: bool
29
+ requires_gpu: bool
30
+ loaded: bool
@@ -0,0 +1,33 @@
1
+ # Copyright (c) 2024-2026, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # SPDX-License-Identifier: MPL-2.0
4
+ # This file is part of BERTrend.
5
+
6
+ from fastapi import APIRouter
7
+
8
+ from bertrend.services.summary_server.models import SummarizerInfo
9
+ from bertrend.services.summary_server.routers.summarize import (
10
+ SUMMARIZER_REGISTRY,
11
+ _summarizer_cache,
12
+ )
13
+
14
+ router = APIRouter()
15
+
16
+
17
+ @router.get("/health")
18
+ def health():
19
+ return {"status": "ok"}
20
+
21
+
22
+ @router.get("/summarizers", response_model=list[SummarizerInfo])
23
+ def list_summarizers():
24
+ return [
25
+ SummarizerInfo(
26
+ name=name,
27
+ description=meta["description"],
28
+ requires_api_key=meta["requires_api_key"],
29
+ requires_gpu=meta["requires_gpu"],
30
+ loaded=name in _summarizer_cache,
31
+ )
32
+ for name, meta in SUMMARIZER_REGISTRY.items()
33
+ ]